/* ============================================================================
   CALENDAR — Day view                      COMPONENTS.md §23 · §24 · §21.1

   Figma: FE Client file, `s/events` node 34017:344265
     p/navbar/local        → navbar.css (already built)
     b/sidebar/left 2      → sidebar.css + menu.css (already built)
     b/body/events/calendar (34017:344270)
       p/body/header       → the H1 band, same shape as collection.css
       Card (30640:549688)
         Calendar / Header            → .calendar__toolbar
         Calendar / Sidebar           → .calendar__side  (Datepicker §24 +
                                        Tabs / Social → Row / To-Do §22.3)
         Calendar / Social / Calendar view → .calendar__view

   ── Why nothing here is copied off the frame ──────────────────────────────
   COMPONENTS.md §23.2 measures Calendar as ~70% UNBOUND and §23 F1/F2 record
   it as the file's least token-bound page — it "will not follow theme or brand
   at all". Root CLAUDE.md rule 1 of the workflow says to use the documented
   token contract and not to read colours off the design. So every raw value in
   the frame is resolved back through the table §23.2 itself supplies:

   | Figma raw            | Resolved to                                      |
   |----------------------|--------------------------------------------------|
   | `#ffffff`            | `surface/raised`                                 |
   | `#f6f6f6`            | `soft/neutral/default`   (segmented track, §21.1)|
   | `#e8e8e8`            | `border/default`         (every grid hairline)   |
   | `#d9d9d9`            | `border/default`         (Button Tertiary, §1.1) |
   | `#262626`            | `content/headline`                               |
   | `#595959`            | `content/primary`                                |
   | `#8c8c8c`            | `content/secondary` as text; `border/strong` as  |
   |                      | the canceled-event outline — see the note below  |
   | `#bfbfbf`            | `content/placeholder`                            |
   | **`#4211a0`**        | `solid/brand/default` · `content/brand` ·        |
   |                      | `border/brand/default`                           |
   | `#ebe6f5`            | `soft/brand/default`     — see the note below    |
   | `#ea0b16`            | `solid/danger/default`   (the live "now" line)   |
   | `#509e2a`            | `content/success`        (Accept icon, §1.1)     |
   | segment drop shadow  | `--elevation-raised`     (DESIGN.md §8.1)        |

   Two of those deserve saying out loud:

   · **`#4211a0` is the BigHeart brand seed.** §23 F1 calls its appearance in
     `Scheduling / Calendar slots` a Critical defect and the THIRD occurrence
     of the class, after `p/avatar` (§16 F1) and `Row / Poll` (§22 F1); root
     CLAUDE.md rule 4 forbids adding a fifth. It appears five times in this
     frame — the day header, the event rail, the event outline, the selected
     datepicker cell, the New button — and is a token in all five here. This
     page is the most brand-visible surface in the app (apps/fe-client
     CLAUDE.md), so it is the one where that matters most.

   · **`#ebe6f5` is `Action/BigHeart/Secondary - Hover (10%)`** — the HOVER
     step of the soft brand ramp, used as an event's resting fill. Datepicker
     F2 (§24.1) flags exactly this substitution as a defect. Bound here to
     `soft/brand/default`, with `soft/brand/hover` kept for actual hover, so
     the ramp reads in the right order. Slightly lighter than the frame.

   · **`#8c8c8c` as a border** is §31.7 layer inversion — a content token used
     as a fill. `border/strong` is the border-layer token for "stronger than
     default" and is used instead; it lands one step lighter than the frame.

   ── Gaps handled rather than reproduced (root CLAUDE.md "Known gaps") ─────
   · **Focus** — §23 has no focus state anywhere and §24.1 F4 calls its absence
     on a date grid a gap "despite full keyboard navigation being expected".
     base.css defines the ring once, on `:focus-visible`; every control here is
     a real `<button>`/`<a>`/`<select>` so it inherits it.
   · **Pressed** — unmodelled in §23; `…/pressed` tokens exist and are used.
   · **Segmented Control §21.1 F1** — active and inactive share
     `content/primary`, so selection rests on the raised fill alone. A weight
     step is added here, as Dropdown §6.2 (the reference implementation) does.
   · **Elevation** — unconsumed in the DS. The active segment uses it.
   · **Status by wording alone** — the canceled event is NOT carried by the
     word "CANCELED" in its title. The frame already gives it three further
     channels (neutral outline, strike-through, and no button role at all) and
     all three are reproduced.

   ── The one extension to the frame ────────────────────────────────────────
   The frame's hour gutter is 12px + 23 rows of 80 + 12px = 1864, i.e. lines at
   00:00 through 23:00, which leaves the last hour of the day undrawn — an
   event at 23:30 would fall outside the grid. Here it is 24 rows, so the
   canvas is 12 + 24 x 80 + 12 = 1944 and the day is whole.

   TODO(tokens): every bare px length in this file is a SIZE.
   DESIGN.md §12.4 records size as not built. No colour, radius, spacing,
   border-width or font-size literal appears anywhere in this file.
   ========================================================================== */

.calendar {
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
  /* Figma: Body 968 in a 1016 wrapper = viewport - navbar - both gutters. The
     same formula sidebar.css and rail.css use, so all three columns end level
     and the grid gets a fixed box to scroll inside. */
  block-size: calc(100dvh - 64px - var(--layout-gutter) * 2);
}

/* --- p/body/header — the H1 band, 72 tall in the frame ------------------- */
.calendar__header {
  display: flex;
  align-items: center;
  gap: var(--space-md);
  flex: none;
  padding-block: var(--space-md);
}

.calendar__title {
  margin: 0;
  flex: 1 1 auto;
  min-inline-size: 0;
}

/* --- Card (30640:549688) — the panel the whole calendar lives in --------- */
.calendar__card {
  display: flex;
  flex: 1 1 auto;
  min-block-size: 0;
  flex-direction: column;
  background: var(--color-surface-raised);
  border-radius: var(--shape-radius-card);
  /* The grid's hairlines and the sticky column run to the card's edge. */
  overflow: hidden;
}

/* ==========================================================================
   Calendar / Header (30640:549689) — 64 tall, p16, gap 16
   ========================================================================== */
.calendar__toolbar {
  display: flex;
  flex: none;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-md);
  padding: var(--space-md);
}

/* `date` — the Controls cluster plus the current date, taking the free space
   so the view switcher, layout switcher and New sit at the inline end. */
.calendar__date {
  display: flex;
  flex: 1 1 auto;
  min-inline-size: 0;
  align-items: center;
  gap: var(--space-md);
}

/* `Controls` — prev / Today / next, gap 4. */
.calendar__controls {
  display: flex;
  flex: none;
  align-items: center;
  gap: var(--space-2xs);
}

/* Headlines/H2 Bold 24/32 in the frame = heading/lg under this brand. */
.calendar__current {
  margin: 0;
  white-space: nowrap;
}

/* ==========================================================================
   Segmented Control / Content (§21.1) — the Day/Week/Month and grid/list
   switchers. Two instances, one component.
   ========================================================================== */
.segmented {
  display: flex;
  flex: none;
  align-items: stretch;
  gap: var(--space-none);
  padding: var(--space-3xs);
  background: var(--color-soft-neutral-default);
  border-radius: var(--shape-radius-input);
}

.segmented__item {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2xs);
  /* §21.1 geometry: item padding `space/xs`, radius `radius/xs`. Height comes
     from the track, which the frame fixes at 32 (the Default size). */
  block-size: 28px;
  padding-inline: var(--space-xs);
  background: none;
  border: var(--border-width-none) solid transparent;
  border-radius: var(--radius-xs);
  color: var(--color-content-primary);
  font-family: var(--font-family-text);
  font-size: var(--font-body-md-size);
  line-height: var(--font-body-md-line-height);
  font-weight: var(--font-weight-regular);
  letter-spacing: var(--font-letter-spacing-default);
  white-space: nowrap;
  cursor: pointer;
  transition: background-color 100ms ease, box-shadow 100ms ease;
}

.segmented__item:hover:not([aria-pressed="true"]):not([aria-disabled="true"]) {
  background: var(--color-soft-neutral-hover);
  color: var(--color-on-soft-neutral);
}

.segmented__item:active:not([aria-disabled="true"]) {
  background: var(--color-soft-neutral-pressed);
}

/* Active — raised out of the sunken track (§21.1: no brand colour anywhere).
   The weight step is the §21.1 F1 fix. */
.segmented__item[aria-pressed="true"] {
  background: var(--color-surface-raised);
  box-shadow: var(--elevation-raised);
  font-weight: var(--font-weight-medium);
}

/* Week / Month and the list layout have no view behind them yet. Same honest
   outcome the left rail's unrouted rows take (router.js): the control is
   visible and reachable, says it is unavailable, and does nothing. */
.segmented__item[aria-disabled="true"] {
  color: var(--color-content-disabled);
  cursor: default;
}

/* ==========================================================================
   Sidebar + Calendar (30640:549690)
   Frame: sidebar 296 at x=16, calendar from x=328 — a 16px gutter each side.
   ========================================================================== */
.calendar__split {
  display: flex;
  flex: 1 1 auto;
  min-block-size: 0;
  align-items: stretch;
  gap: var(--space-md);
  padding-inline: var(--space-md);
  padding-block-end: var(--space-md);
}

/* --- Calendar / Sidebar (30640:549691) ---------------------------------- */
.calendar__side {
  display: flex;
  flex: none;
  inline-size: 296px;
  flex-direction: column;
  gap: var(--space-md);
  /* The invitation list is eleven rows deep in the frame and open-ended in
     life, so the scroll lives here and the grid keeps its own. */
  overflow-y: auto;
}

/* ==========================================================================
   Calendar / Sidebar / Datepicker  (§24.1 — "fully token-bound", the
   counter-example to Calendar. Bound as §24.1 specifies, not as §23 draws.)
   ========================================================================== */
.datepicker {
  display: flex;
  flex: none;
  flex-direction: column;
  gap: var(--space-sm);
}

/* `Date and Time` — the year and month selects, two Input / Default / Base
   (§2.1, the reference implementation for focus). field.css owns them. */
.datepicker__pickers {
  display: flex;
  gap: var(--space-xs);
}

.datepicker__pickers .field {
  flex: 1 1 0;
  min-inline-size: 0;
}

/* `Header` — Su..Sa. `Grid` — six weeks of seven cells. One 7-column grid
   carries both, so a day can never fall under the wrong weekday name. */
.datepicker__grid {
  display: grid;
  grid-template-columns: repeat(7, 1fr);
  gap: var(--space-3xs);
}

.datepicker__weekday {
  display: flex;
  align-items: center;
  justify-content: center;
  block-size: 28px;
  color: var(--color-content-secondary);
}

/* Datepicker / Grid / Days / Cell — eleven variant axes in §24.1; this view
   needs In View, Today, Selected and Hovered. */
.datepicker__day {
  display: flex;
  align-items: center;
  justify-content: center;
  block-size: 28px;
  padding: var(--space-none);
  background: none;
  border: var(--border-width-none) solid transparent;
  border-radius: var(--radius-sm);
  color: var(--color-content-primary);
  font-family: var(--font-family-text);
  font-size: var(--font-body-md-size);
  line-height: var(--font-body-md-line-height);
  font-weight: var(--font-weight-regular);
  letter-spacing: var(--font-letter-spacing-default);
  cursor: pointer;
  transition: background-color 100ms ease, color 100ms ease;
}

/* `In View = false` — the leading and trailing days of the adjacent months.
   The frame greys them; `content/placeholder` is the token for text that is
   present but not the subject. */
.datepicker__day--muted {
  color: var(--color-content-placeholder);
}

.datepicker__day:hover {
  /* §24.1 F1: `Months / Cell` Hover is bound to `solid/disabled` — the
     disabled token as a hover affordance. `List / Days / Cell` already uses
     the correct one, and that is what is used here. */
  background: var(--color-soft-neutral-default);
  color: var(--color-on-soft-neutral);
}

.datepicker__day:active {
  background: var(--color-soft-neutral-pressed);
}

/* `Today` — a ring, so it survives being unselected. */
.datepicker__day--today {
  border-width: var(--border-width-thin);
  border-color: var(--color-border-brand-default);
  font-weight: var(--font-weight-medium);
}

/* `Selected` — §24.1: selected cells use `on-solid/brand` on the brand fill,
   which is the §4.4 pairing contract. */
.datepicker__day[aria-pressed="true"] {
  background: var(--color-solid-brand-default);
  border-color: var(--color-border-brand-default);
  color: var(--color-on-solid-brand);
  font-weight: var(--font-weight-medium);
}

.datepicker__day[aria-pressed="true"]:hover {
  background: var(--color-solid-brand-hover);
  color: var(--color-on-solid-brand);
}

.datepicker__day[aria-pressed="true"]:active {
  background: var(--color-solid-brand-pressed);
}

/* ==========================================================================
   Row / Section Title (§22.4) — "Upcoming Invitations" + the Declined link
   ========================================================================== */
.calendar__section-title {
  display: flex;
  align-items: center;
  gap: var(--space-xs);
  padding-block: var(--space-xs);
}

.calendar__section-title h2 {
  margin: 0;
  flex: 1 1 auto;
  min-inline-size: 0;
}

/* `Rows Invitations` — Row / To-Do (§22.3), which todo.css already owns. */
.calendar__invitations {
  display: flex;
  flex-direction: column;
  gap: var(--space-2xs);
  margin: 0;
  padding: 0;
  list-style: none;
}

/* ==========================================================================
   Calendar / Social / Calendar view (30640:549693)
   ========================================================================== */

/* calendar.js writes the view into this node on every repaint, so the node
   itself carries the sizing - otherwise the 1944px canvas has nothing to push
   against and grows the page instead of scrolling inside the card. */
.calendar__grid-mount {
  display: flex;
  flex: 1 1 auto;
  min-inline-size: 0;
  min-block-size: 0;
}

.calendar__view {
  display: flex;
  flex: 1 1 auto;
  min-inline-size: 0;
  min-block-size: 0;
  flex-direction: column;
}

/* The hour gutter's width, and the grid's scale. Both are sizes, so both are
   literals — but each appears exactly once. */
.calendar__view {
  --cal-gutter: 80px;
  --cal-hour: 80px;
  /* The 12px lead-in and lead-out exist so the 00:00 and 24:00 labels, which
     straddle their gridline, are not clipped. Straight off the frame's hour
     column: cells of 12, 23 x 80, 12. */
  --cal-pad: 12px;
  --cal-canvas: calc(var(--cal-pad) * 2 + var(--cal-hour) * 24);
}

/* --- Headers / View (7146:35381) — 38 tall ------------------------------- */
.calendar__gridhead,
.calendar__allday {
  display: flex;
  flex: none;
  align-items: stretch;
  background: var(--color-surface-raised);
}

/* Column / Cell — border-block-end + border-inline-end on every cell in the
   frame. Declared once here and shared by the four cell kinds. */
.calendar__cell {
  border-block-end: var(--border-width-thin) solid var(--color-border-default);
  border-inline-end: var(--border-width-thin) solid var(--color-border-default);
}

/* The timezone cell and the "All day" cell — both sit above the hour gutter,
   so both take its width. */
.calendar__corner {
  display: flex;
  flex: none;
  inline-size: var(--cal-gutter);
  align-items: center;
  justify-content: center;
  padding-inline: var(--space-2xs);
  color: var(--color-content-secondary);
  text-align: center;
}

/* Headers / Days / Cell — px16 py8 in the frame. */
.calendar__dayhead {
  display: flex;
  flex: 1 1 0;
  min-inline-size: 0;
  flex-direction: column;
  align-items: flex-start;
  padding: var(--space-xs) var(--space-md);
}

/* The frame's day title is brand-coloured because the day it draws IS today.
   Brand is the "this is now" channel here, not the day-header style. */
.calendar__dayname {
  color: var(--color-content-headline);
  font-weight: var(--font-weight-bold);
}

.calendar__dayname--today {
  color: var(--color-content-brand);
}

/* --- Headers / All day slot (7247:71379) --------------------------------- */
.calendar__allday {
  min-block-size: 42px;
}

.calendar__allday-slots {
  display: flex;
  flex: 1 1 0;
  min-inline-size: 0;
  flex-direction: column;
  padding: var(--space-px);
}

/* --- Overflow (7146:35382) — the only scrolling box in the grid ---------- */
.calendar__scroller {
  flex: 1 1 auto;
  min-block-size: 0;
  overflow: auto;
  /* The scroller's own hairline column would end at the content's height, not
     the box's, so the gutter's inline-end rule is drawn on the canvas. */
  overscroll-behavior: contain;
}

.calendar__canvas {
  display: flex;
  align-items: stretch;
  block-size: var(--cal-canvas);
}

/* --- Calendar rows - Time (7445:44692) — the hour gutter ----------------- */
.calendar__times {
  position: relative;
  flex: none;
  inline-size: var(--cal-gutter);
  border-inline-end: var(--border-width-thin) solid var(--color-border-default);
}

/* Each label is centred ON its gridline, which is what the frame's 12px
   lead-in is for. `--at` is the line's offset, set inline by calendar.js. */
.calendar__time {
  position: absolute;
  inset-inline: var(--space-none);
  inset-block-start: var(--at);
  transform: translateY(-50%);
  padding-inline-end: var(--space-xs);
  color: var(--color-content-secondary);
  text-align: end;
}

/* --- Days (7146:35385) --------------------------------------------------- */
.calendar__days {
  position: relative;
  flex: 1 1 0;
  min-inline-size: 0;
}

/* Days / BG → Column — one hairline per hour. A border rather than a
   background gradient so it is the same `border/default` hairline as every
   other cell edge in the grid. */
.calendar__hour {
  position: absolute;
  inset-inline: var(--space-none);
  inset-block-start: var(--at);
  border-block-start: var(--border-width-thin) solid var(--color-border-default);
}

/* Days / Events (7146:35388) */
.calendar__events {
  position: absolute;
  inset: var(--space-none);
}

/* Live indicator (7146:35397) — the danger hairline plus its 9px ringed dot.
   `content/danger` would be the token for danger-coloured TEXT; this is a
   filled 1px rule and a filled dot, so both take the solid ramp (§4.4). */
.calendar__now {
  position: absolute;
  inset-inline: var(--space-none);
  inset-block-start: var(--at);
  block-size: var(--border-width-thin);
  background: var(--color-solid-danger-default);
  /* Above the event blocks, which are opaque. */
  z-index: 1;
  pointer-events: none;
}

.calendar__now::before {
  content: "";
  position: absolute;
  inset-block-start: 50%;
  inset-inline-start: 0;
  inline-size: 9px;
  block-size: 9px;
  transform: translate(-50%, -50%);
  background: var(--color-solid-danger-default);
  /* The frame's white ring, so the dot reads against an event block behind it.
     surface/raised is the card it sits on, which is what the ring imitates. */
  border: var(--border-width-thin) solid var(--color-surface-raised);
  border-radius: var(--radius-full);
}

/* ==========================================================================
   Calendar / Calendar view / Components / Column / Event (44800:201257)
   One component for every block in the grid and in the all-day slot. Height
   comes from the duration, and the content is clipped — which is exactly how
   the frame's 20px and 40px blocks show one line and two.
   ========================================================================== */
.cal-event {
  display: flex;
  align-items: stretch;
  /* The frame's `pb-px pr-[8px]`: a hairline gap between stacked blocks and an
     8px inset so a block never touches the next column. */
  padding-block-end: var(--space-px);
  padding-inline-end: var(--space-xs);
  background: none;
  border: var(--border-width-none) solid transparent;
  text-align: start;
  cursor: pointer;
}

/* In the grid the block is positioned by time; in the all-day slot it is just
   a 20px row in a stack. `--top`, `--height`, `--lane-start` and
   `--lane-size` are set inline by calendar.js. */
.calendar__events .cal-event {
  position: absolute;
  inset-block-start: var(--top);
  block-size: var(--height);
  inset-inline-start: var(--lane-start, 0%);
  inline-size: var(--lane-size, 100%);
}

.calendar__allday-slots .cal-event {
  block-size: 20px;
}

/* `Wrapper` — the painted body. */
.cal-event__wrap {
  display: flex;
  flex: 1 1 auto;
  min-inline-size: 0;
  align-items: stretch;
  gap: var(--space-3xs);
  padding-inline: var(--space-3xs);
  background: var(--color-soft-brand-default);
  border: var(--border-width-thin) solid transparent;
  border-radius: var(--radius-sm);
  overflow: hidden;
  transition: background-color 100ms ease, border-color 100ms ease;
}

.cal-event:hover .cal-event__wrap {
  background: var(--color-soft-brand-hover);
}

.cal-event:active .cal-event__wrap {
  background: var(--color-soft-brand-pressed);
}

/* `Highlight` — the 2px rail. */
.cal-event__bar {
  flex: none;
  inline-size: 2px;
  border-radius: var(--radius-xs);
  background: var(--color-solid-brand-default);
}

.cal-event__body {
  display: flex;
  flex: 1 1 auto;
  min-inline-size: 0;
  flex-direction: column;
  justify-content: center;
}

/* `Name Wrapper` — title, then the icon slot at the inline end. */
.cal-event__name {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3xs);
}

.cal-event__title {
  margin: 0;
  flex: 1 1 auto;
  min-inline-size: 0;
  color: var(--color-content-headline);
  font-weight: var(--font-weight-bold);
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

.cal-event__icons {
  display: flex;
  flex: none;
  align-items: center;
  gap: var(--space-3xs);
  /* py-[4px] in the frame, so the 12px glyphs centre on the 20px line. */
  padding-block: var(--space-2xs);
  color: var(--color-content-primary);
}

.cal-event__sub,
.cal-event__place {
  margin: 0;
  display: flex;
  align-items: center;
  gap: var(--space-3xs);
  color: var(--color-content-primary);
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}

.cal-event__meta {
  margin: 0;
  display: flex;
  align-items: center;
  gap: var(--space-3xs);
  color: var(--color-content-primary);
  white-space: nowrap;
}

.cal-event__meta .icon,
.cal-event__place .icon {
  flex: none;
  color: var(--color-content-primary);
}

.cal-event__text {
  overflow: hidden;
  text-overflow: ellipsis;
}

/* --- state = past (9825:90744) ------------------------------------------
   Raised fill, brand outline, and the title steps down from
   `content/headline` to `content/primary` — the frame's own dimming, which is
   a real second channel rather than colour alone. */
.cal-event--past .cal-event__wrap {
  background: var(--color-surface-raised);
  border-color: var(--color-border-brand-default);
}

.cal-event--past:hover .cal-event__wrap {
  background: var(--color-soft-brand-default);
  border-color: var(--color-border-brand-hover);
}

.cal-event--past .cal-event__title {
  color: var(--color-content-primary);
}

/* --- state = canceled (7147:46143) --------------------------------------
   Raised fill, neutral outline, struck through — and rendered as a <div>, not
   a <button>, because the frame drops the interactive layer too. Four
   channels, so the word "CANCELED:" in the title is never load-bearing. */
.cal-event--canceled {
  cursor: default;
}

.cal-event--canceled .cal-event__wrap {
  background: var(--color-surface-raised);
  border-color: var(--color-border-strong);
}

.cal-event--canceled .cal-event__bar {
  background: var(--color-border-strong);
}

.cal-event--canceled .cal-event__title,
.cal-event--canceled .cal-event__sub {
  color: var(--color-content-primary);
  text-decoration: line-through;
}

/* --- Multiday — the block runs off the column's inline end --------------- */
.cal-event--continues {
  padding-inline-end: var(--space-none);
}

.cal-event--continues .cal-event__wrap {
  border-start-end-radius: var(--radius-none);
  border-end-end-radius: var(--radius-none);
}

/* --- Empty day ----------------------------------------------------------
   Not in the frame, which only draws the day that has content. Empty State /
   Body (§25) is the bound component for it. */
.calendar__empty {
  position: absolute;
  inset-inline: var(--space-none);
  inset-block-start: var(--at);
  margin: 0;
  padding-inline: var(--space-md);
  color: var(--color-content-secondary);
  text-align: center;
}
