/* schedule-calendar.css — "What's scheduled": the Control Centre tile and the
   calendar it expands into.

   Built on the app-shell design system (src/public/app-shell.css) — every
   colour, radius and font here is one of its tokens. Nothing new is invented:
   the three content colours are --accent (email broadcast), --plum (Facebook)
   and --rose (community), which already exist and already read as a family.

   ⚠️ COLOUR IS NEVER THE ONLY SIGNAL. Every chip carries a glyph as well as a
   rail colour, and every state is drawn by the BORDER rather than by a colour
   swap alone. That is an accessibility requirement for colour-blind readers,
   and independently it is what makes a day with five items scannable. */

/* Three channel colours, one per type. `--sch-email` is gone with the automated
   kinds; broadcast keeps --accent, which is the one it always rendered as. */
.sch-tile, .sch-full { --sch-social: var(--plum); --sch-broadcast: var(--accent); --sch-community: var(--rose); }

.sch-t-social    { --sch-c: var(--sch-social); }
.sch-t-broadcast { --sch-c: var(--sch-broadcast); }
.sch-t-community { --sch-c: var(--sch-community); }

.sch-loading, .sch-error { padding: 34px 22px; text-align: center; color: var(--text-3); font-size: 13.5px; }
.sch-error { color: var(--danger); }

/* ── the tile ───────────────────────────────────────────────────────────── */

.sch-tile-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px; padding: 18px 22px; border-bottom: 1px solid var(--border-soft);
}
.sch-tile-title {
  font-family: "Bricolage Grotesque", sans-serif; font-weight: 700; font-size: 17px;
  letter-spacing: -0.01em; display: flex; align-items: center; gap: 10px;
}
.sch-count-pill {
  background: var(--surface-3); color: var(--text-2); font-family: "JetBrains Mono", monospace;
  font-size: 11px; font-weight: 500; padding: 2px 8px; border-radius: 999px;
}
.sch-tile-actions { display: flex; align-items: center; gap: 12px; }
.sch-tzline {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 11.5px; color: var(--text-3);
}
.sch-tzline b { color: var(--text-2); font-weight: 600; }
.sch-tzline svg { width: 12px; height: 12px; }

.sch-week {
  display: grid; grid-template-columns: repeat(7, minmax(0, 1fr));
  gap: 1px; background: var(--border-soft);
}
.sch-daycol { background: var(--surface); padding: 12px 12px 14px; }
.sch-daycol.sch-today { background: var(--accent-softer); }
.sch-dow {
  font-family: "JetBrains Mono", monospace; font-size: 9.5px;
  letter-spacing: 0.14em; color: var(--text-3);
}
.sch-today .sch-dow { color: var(--accent); }
.sch-dnum {
  font-family: "Bricolage Grotesque", sans-serif; font-weight: 700;
  font-size: 22px; margin: 2px 0 9px;
}
.sch-today .sch-dnum { color: var(--accent); }
.sch-dots { display: flex; gap: 4px; flex-wrap: wrap; }
.sch-dot { width: 9px; height: 9px; border-radius: 3px; background: var(--sch-c); }
/* Waiting on you gets a halo rather than a different colour — the type must
   still be readable, and the halo is the second channel. */
/* The needs-you dot wears the same red as its chip — one meaning, one colour. */
.sch-dot-need { box-shadow: 0 0 0 2px var(--danger-soft); }
.sch-dot-bad { background: var(--danger); }
.sch-none { color: var(--text-4); font-size: 12px; }
.sch-dl-mini {
  display: inline-flex; align-items: center; gap: 5px; margin-bottom: 6px;
  font-size: 9.5px; font-weight: 700; color: var(--warn);
}
.sch-dl-mini svg { width: 10px; height: 10px; }

.sch-work { border-top: 1px solid var(--border-soft); padding: 14px 22px 16px; background: var(--surface-2); }
.sch-work-head {
  display: flex; align-items: center; gap: 9px; margin-bottom: 11px;
  font-family: "JetBrains Mono", monospace; font-size: 10px;
  letter-spacing: 0.16em; color: var(--text-3);
}
.sch-work-head i { flex: 1; height: 1px; background: var(--border-soft); }
.sch-work-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px; }
.sch-clear { color: var(--text-3); font-size: 13px; grid-column: 1 / -1; }

/* ── chips ──────────────────────────────────────────────────────────────── */

.sch-chip {
  display: flex; align-items: stretch; width: 100%; text-align: left;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: 9px; overflow: hidden; padding: 0; cursor: pointer;
  font-family: inherit; transition: border-color .12s, transform .1s;
  /* ⚠️ 48px minimum touch target (design system §4, "no exceptions"). A chip is
     the primary control on this screen and is tapped on a phone. */
  min-height: var(--rk-touch-target, 48px);
}
.sch-chip:hover { border-color: var(--border-strong); }
.sch-rail { width: 3px; flex-shrink: 0; background: var(--sch-c); }
.sch-body { padding: 6px 9px; flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; justify-content: center; }
.sch-top { display: flex; align-items: center; gap: 6px; }
.sch-glyph { display: inline-flex; color: var(--sch-c); }
.sch-glyph svg { width: 11px; height: 11px; display: block; }
.sch-time { font-family: "JetBrains Mono", monospace; font-size: 9.5px; color: var(--text-3); }
.sch-title {
  font-size: 11.5px; font-weight: 600; line-height: 1.3; color: var(--text);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.sch-count { margin-left: auto; font-family: "JetBrains Mono", monospace; font-size: 9px; color: var(--text-3); }
/* ⚠️ THE FLAG IS RED NOW, NOT AMBER. Red means "act" across the whole screen —
   see the state block below and the matching swap in control-centre.css. */
.sch-flag { margin-left: auto; font-size: 8.5px; font-weight: 700; color: var(--danger); letter-spacing: 0.05em; }

/* "I'll add the photo later" — migration 598. AMBER, never red: red on this page
   means "you can act on this now", and this one he cannot act on in a tap, it
   wants a file. The camera rides with the word so the meaning survives a
   greyscale print and a colour-blind reader, same rule as the state marks. */
.sch-flag-media {
  display: inline-flex; align-items: center; gap: 3px; color: var(--warn);
  background: color-mix(in srgb, var(--warn) 12%, transparent);
  border-radius: 999px; padding: 1px 5px 1px 4px;
}
.sch-flag-media svg { width: 9px; height: 9px; display: block; }
/* ⚠️ THE WHOLE CHIP TURNS AMBER, NOT JUST THE PILL — and the first build of
   this got it wrong in a way only a render caught. Recolouring the rail and the
   flag while leaving `.sch-s-needs_you`'s red ground and red dashed border in
   place produced a RED chip wearing an amber label: the exact contradiction the
   colour rule exists to prevent, since red on this page means "you can act on
   this now" and this one wants a file. Dashed stays — it is still unfinished —
   and the mark goes amber with everything else.

   Specificity: (0,3,0), which beats `.sch-s-needs_you` (0,1,0) outright rather
   than relying on source order. `.cc-page .btn` has won four ties on order in
   this project; none of them should have been ties. */
.sch-chip.sch-needs-media {
  background: var(--warn-soft);
  border-style: dashed;
  border-color: var(--warn);
}
.sch-chip.sch-needs-media .sch-rail { background: var(--warn); }
.sch-chip.sch-needs-media .sch-mark { color: var(--warn); }

/* ⚠️ A HELD SEND DOES NOT PULSE. `paused` shares the `sending` skin, and that
   skin animates its mark to say "this is moving right now" — which on a send
   the coach deliberately stopped is the screen contradicting him. Caught by
   looking at the render, not by reasoning about it. Same specificity trick as
   above: (0,3,0) beats `.sch-s-sending .sch-mark` (0,2,0) outright. */
.sch-chip.sch-paused .sch-mark { animation: none; }

/* The state mark. Always present, always FIRST in the row, so the eye finds the
   same pixel on every chip instead of hunting for a differently-placed signal. */
.sch-mark { display: inline-flex; flex-shrink: 0; }
.sch-mark svg { width: 11px; height: 11px; display: block; }

/* The Page mark, once more than one account is connected. */
.sch-acct {
  width: 14px; height: 14px; border-radius: 4px; background: var(--accent); color: #fff;
  font-size: 8px; font-weight: 700; display: inline-flex; align-items: center;
  justify-content: center; flex-shrink: 0;
}
/* A picture in the post is the fastest thing to recognise on a crowded day. */
.sch-thumb { width: 30px; flex-shrink: 0; background-size: cover; background-position: center; }

/* ══ THE SIX STATES ═════════════════════════════════════════════════════════
   Alex, 2026-08-26, approving round 2. The rule the whole screen rests on:

     ⚠️ THE LEFT RAIL IS THE ONLY PLACE TYPE IS COLOURED. Fill, border and mark
     belong to STATE. Colour used to answer "what kind of thing is this?" —
     which the glyph already answered — leaving nothing to answer the question
     a coach actually opens this screen with.

   And the one that matters most:

     ⚠️ RED APPEARS EXACTLY ONCE — on `needs_you`. A failure is BLACK, not red,
     because red now means "you can still do something about this" and a send
     that already missed its slot is a fact. Adding red anywhere else costs the
     screen the thing that makes it work: at a glance, red IS the to-do list. */

/* NEEDS YOU — red. Dashed, because an unfinished thing should look unfinished. */
.sch-s-needs_you {
  background: var(--danger-soft);
  border-style: dashed;
  border-color: var(--danger);
}
.sch-s-needs_you .sch-mark { color: var(--danger); }
.sch-s-needs_you .sch-title { color: var(--text); }

/* READY — green. Approved, booked, nothing owed. Calm on purpose. */
.sch-s-ready { background: var(--good-soft); border-color: #bfe2ce; }
.sch-s-ready .sch-mark { color: var(--good); }

/* SENDING — amber, and moving. Keeps the meaning amber already has on the
   Control Centre's rows: happening now, watch it. */
.sch-s-sending { background: var(--warn-soft); border-color: #ecd3a2; }
.sch-s-sending .sch-mark { color: var(--warn); animation: sch-pulse 1.8s ease-in-out infinite; }
@keyframes sch-pulse { 0%, 100% { opacity: 1; } 50% { opacity: .45; } }
@media (prefers-reduced-motion: reduce) { .sch-s-sending .sch-mark { animation: none; } }

/* WENT OUT — green tick, drained back. It is a record, not a job: it must not
   compete with next week for attention. The rail fades but does not vanish,
   so the channel is still readable down the column. */
.sch-s-sent { background: var(--surface-2); border-color: var(--border-soft); }
.sch-s-sent .sch-mark { color: var(--good); }
.sch-s-sent .sch-rail { opacity: .4; }
.sch-s-sent .sch-title { color: var(--text-3); font-weight: 500; }
.sch-s-sent .sch-glyph { color: var(--text-4); }

/* DIDN'T GO — black cross on white. High contrast, no colour: it is the one
   thing on the grid that is neither work nor done, and it should read as a
   hole in the record rather than as an alarm. */
.sch-s-missed { background: var(--surface); border-color: var(--border-strong); }
.sch-s-missed .sch-mark { color: var(--text); }
.sch-s-missed .sch-title { color: var(--text); }

/* YOU SAID NO — struck through and faded. Visible so the slot is not
   mysteriously empty; quiet so it never reads as something to do. */
.sch-s-rejected { background: var(--surface); border-color: var(--border-soft); opacity: .55; }
.sch-s-rejected .sch-mark { color: var(--text-3); }
.sch-s-rejected .sch-title { color: var(--text-3); text-decoration: line-through; font-weight: 500; }
.sch-s-rejected .sch-rail { opacity: .4; }

/* ── the expanded calendar ──────────────────────────────────────────────── */

.sch-full { padding: 4px 0 8px; }
.sch-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 12px; }
.sch-nav { display: flex; align-items: center; gap: 12px; }
.sch-month-label { font-family: "Bricolage Grotesque", sans-serif; font-weight: 700; font-size: 19px; }
.sch-prev, .sch-next { padding: 7px 12px; }

/* ── NEXT 7 DAYS / MONTH ────────────────────────────────────────────────────
   Alex, 2026-08-26: *"You also got rid of the collapsible bit for showing just
   the current week ahead… then you can expand it if you want."* The collapse and
   the expand are one control, in the segmented shape Google's own view switcher
   uses — a single pill, the active view filled in. */
.sch-views {
  display: inline-flex; align-items: center; gap: 2px;
  background: var(--surface-3); border: 1px solid var(--border);
  border-radius: 999px; padding: 2px;
}
.sch-view {
  padding: 6px 13px; border-radius: 999px; border: 0; background: transparent;
  font-size: 12.5px; font-weight: 600; color: var(--text-3);
}
.sch-view:hover { color: var(--text-2); }
.sch-view-on { background: var(--surface); color: var(--text); box-shadow: 0 1px 3px rgba(21, 23, 43, .10); }

.sch-filters {
  display: flex; align-items: center; justify-content: space-between; gap: 16px; flex-wrap: wrap;
  background: var(--surface); border: 1px solid var(--border); border-radius: 14px;
  padding: 10px 14px; margin-bottom: 14px;
}
.sch-filter-row { display: flex; align-items: center; gap: 7px; flex-wrap: wrap; }
.sch-filter-right { display: flex; align-items: center; gap: 9px; }

.sch-filter {
  display: inline-flex; align-items: center; gap: 6px;
  border: 1px solid var(--border); background: var(--surface); border-radius: 999px;
  padding: 7px 13px; font-size: 12.5px; font-weight: 500; color: var(--text-3);
  font-family: inherit; cursor: pointer; min-height: var(--rk-touch-target, 48px);
  transition: background .12s, border-color .12s, color .12s;
}
.sch-filter .sch-glyph { color: var(--text-4); }
/* An OFF filter is visibly off — greyed, not merely un-tinted. Silently hiding
   a whole content type behind a chip that looks the same either way is how a
   coach concludes nothing is scheduled. */
.sch-filter.sch-on { background: var(--accent-softer); border-color: #c9bcff; color: var(--text); font-weight: 600; }
.sch-filter.sch-on .sch-glyph { color: var(--sch-c); }
.sch-fcount { font-family: "JetBrains Mono", monospace; font-size: 10px; color: var(--text-3); }

/* ⚠️ IT IS A DOOR, SO IT LOOKS LIKE ONE. Alex, 2026-08-26: *"Waiting for you,
   when you click on Waiting for you, actually takes you to the things that
   you're waiting on."* It was a passive chip naming work it could not reach —
   the surest way to teach someone to stop pressing things. The chevron is the
   part that says it goes somewhere; the cursor and the hover are the rest. */
.sch-waiting {
  display: inline-flex; align-items: center; gap: 6px;
  background: var(--warn-soft); border: 1px solid #f0dcc0; color: var(--warn);
  border-radius: 999px; padding: 6px 12px; font-size: 12.5px; font-weight: 600;
  font-family: inherit; cursor: pointer;
  transition: background .12s, border-color .12s;
}
.sch-waiting:hover { background: #f7e6c8; border-color: var(--warn); }
.sch-waiting:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.sch-waiting svg { width: 12px; height: 12px; }
.sch-wchev { width: 10px; height: 10px; opacity: .75; }

/* The zone, riding on the date line. Quiet enough to read as a suffix rather
   than a second value, and it carries the native picker invisibly on top. */
.sch-label-tz {
  position: relative; display: inline-block;
  font-family: "JetBrains Mono", monospace; font-size: 10px; font-weight: 600;
  color: var(--text-3); letter-spacing: 0.05em; margin-left: 6px;
  vertical-align: 1px; cursor: pointer;
}
.sch-label-tz:hover { color: var(--accent); }
/* The native select sits invisibly over the abbreviation: one tap, the
   platform's own picker, no bespoke dropdown to keyboard-trap anybody.
   ⚠️ Its clicks are stopped from bubbling in JS — the label around it is the
   "Today" control on a phone. */
.sch-label-tz .sch-tz-sel {
  position: absolute; inset: -6px -4px; width: auto; height: auto;
  opacity: 0; cursor: pointer; font-family: inherit;
}

/* Both view labels ship; CSS picks which is visible. Desktop keeps the words. */
.sch-view-short { display: none; }

/* ⚠️ NO STANDALONE TIMEZONE CARD. The `.sch-tz` block that lived here was a
   48px control in the filter row for a decision made once. It is now the
   `.sch-label-tz` suffix on the date line above — same native select, same one
   tap, no box. Named here rather than silently removed, because "put the
   timezone back where you can see it" is a reasonable-sounding instinct and the
   answer is that it never left: it moved to where its meaning is. */

.sch-month { border: 1px solid var(--border); border-radius: 14px; overflow: hidden; background: var(--border-soft); }
.sch-hrow, .sch-grid { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 1px; background: var(--border-soft); }
.sch-hcell {
  background: var(--surface-2); padding: 8px 10px;
  font-family: "JetBrains Mono", monospace; font-size: 9.5px;
  letter-spacing: 0.14em; color: var(--text-3);
}
/* ⚠️ `pan-y` TELLS THE BROWSER THE SIDEWAYS AXIS IS OURS. Without it, a
   horizontal drag can trigger the browser's own back-swipe or overscroll before
   our handler ever sees it — the gesture would work on some phones and navigate
   away on others. Vertical stays with the page, which is what lets the calendar
   be scrolled past to the cards below. */
/* ⚠️ AND `overscroll-behavior-x: contain` IS THE OTHER HALF, for the TRACKPAD.
   `touch-action` covers touchscreens; it does nothing for a two-finger swipe on
   a laptop, which is what Alex was using on 2026-08-27 when the gesture kept
   navigating the app away — *"you could accidentally end up swiping to the
   previous page and then lose what you're on."* This is the purpose-built
   property for "the browser's horizontal navigation gesture does not start
   here", and it belongs on the calendar because the calendar is the one place
   on the page where sideways means something. */
.sch-grid {
  border-top: 1px solid var(--border-soft);
  touch-action: pan-y;
  overscroll-behavior-x: contain;
}
/* ⚠️ SIX ROWS MUST FIT THE WINDOW — that is the whole point of R3. The grid
   takes whatever the viewport has left after the shell's chrome, the compact
   bar, this header and the filter strip, and divides it by six. `min-height`
   is the floor for a short window (and for a phone, where the grid becomes a
   list anyway); without the calc, six rows at a fixed 126px push the last two
   under the fold on a 900px laptop, which is exactly the complaint. */
.sch-full .sch-grid { grid-auto-rows: minmax(96px, calc((100vh - 330px) / 6)); }

/* ⚠️ THE STRIP IS ONE ROW, SO IT GETS THE HEIGHT ALL SIX WOULD HAVE SHARED —
   that is the whole reason to be in it. A day with five things on it shows all
   five without a hover, which is exactly the complaint the month view answers
   with an overlay. Capped so it cannot push the cards below off the screen. */
/* `auto` rather than a viewport fraction: the row is as tall as the busiest of
   the seven days needs and not one pixel more. A fixed 560px left six columns of
   white space under a single chip. The 240px floor keeps a quiet week from
   collapsing into a strip of date numbers. */
.sch-full .sch-strip .sch-grid { grid-auto-rows: minmax(240px, auto); }
.sch-strip .sch-hcell { text-transform: none; }
/* Room to breathe, so nothing is clipped and the "+N more" rarely appears. */
@media (min-width: 901px) {
}
.sch-cell {
  background: var(--surface); padding: 7px 7px 9px;
  display: flex; flex-direction: column; gap: 4px; min-height: 96px;
  overflow: hidden;
  position: relative;
}

/* ══ HOVERING A DAY SHOWS ALL OF IT ═════════════════════════════════════════
   Alex, 2026-08-26, looking at a day whose second chip was sliced in half:
   *"you can't see what's below on the day when you're over it. It's kind of
   half covered up… when you hover over it, maybe the day should expand like a
   very gentle overlay, just open up without pushing everything else around
   it… you're going to have more than one thing on each day."*

   ⚠️ THIS ONE IS GOOGLE'S, AND HIS INSTINCT MATCHED IT. Google Calendar's month
   view clips a busy day too, and its answer is a "+N more" POPOVER — an overlay
   that floats above the grid rather than growing the row. Searched rather than
   recalled (2026-08-26).

   ⚠️ IT MUST NOT REFLOW. The cell keeps its place in the grid; a floating layer
   is what expands. Growing the cell would push every row below it down, which
   is a worse jolt than the clipping it fixes — and on a hover, of all things.

   `min-height` rather than `height`, so a day with eight items grows to fit
   instead of clipping again inside its own overlay. */
.sch-cell:hover,
.sch-cell:focus-within {
  z-index: 30;
  overflow: visible;
  /* ⚠️ `align-self: start` + `height: max-content` IS WHAT MAKES THIS NOT
     REFLOW. The grid's rows are sized by `grid-auto-rows` — a fixed length —
     so a cell that grows past its row overflows it and every other row stays
     exactly where it was. Without this the cell stays stretched to 96px and the
     panel behind it is 96px tall while the chips spill out over bare grid.
     `min-height: 100%` keeps a quiet day from SHRINKING on hover. */
  align-self: start;
  height: max-content;
  min-height: 100%;
}
.sch-cell:hover::after,
.sch-cell:focus-within::after {
  /* The floating panel is the cell's own background, lifted. Drawn as a
     pseudo-element behind the content (z-index:-1) so no wrapper is needed and
     nothing about the DOM changes on hover. */
  content: '';
  position: absolute;
  inset: -1px;
  background: var(--surface);
  border-radius: 10px;
  box-shadow: 0 10px 28px rgba(21, 23, 43, .14), 0 0 0 1px var(--border);
  z-index: -1;
  pointer-events: none;
}
/* ⚠️ WHICH CHIPS ARE HIDDEN IS DECIDED BY MEASUREMENT, IN `fitCells`. It used
   to be `nth-child(n+4)` — a fixed three per cell — and three is a fiction: the
   grid divides whatever the window has left by six, so on a 900px laptop a row
   is 96px and exactly ONE chip fits. The second was drawn half-height and cut
   off, which is the artefact he pointed at. CSS cannot know the row height, so
   the JS marks the ones that do not fit and this rule hides them.

   Phones get the un-clipped list: the grid is a single column there, so the
   height it costs is the height the day actually needs — `fitCells` returns
   early below 901px and never adds the class. */
.sch-daylist { display: flex; flex-direction: column; gap: 4px; }
.sch-daylist > .sch-clipped { display: none; }
.sch-more.sch-clipped { display: none; }
/* The reveal: what was measured out comes back, and the count that described it
   goes away — while the whole day is showing, "+2 more" is a lie. An OPENED cell
   keeps its button, because that one says "Show less" and hiding it would trap
   the day open. */
.sch-cell:hover .sch-daylist > .sch-clipped,
.sch-cell:focus-within .sch-daylist > .sch-clipped { display: flex; }
.sch-cell:hover .sch-more:not(.sch-more-less),
.sch-cell:focus-within .sch-more:not(.sch-more-less) { display: none; }

/* ⚠️ NO ANIMATION ON THE PANEL. A grow/fade on hover across 42 cells is exactly
   the "jittery, keeps flickering" feeling he was describing; the shadow appears
   and the content is simply there. Motion here would cost more than it buys. */
@media (prefers-reduced-motion: no-preference) {
  .sch-cell::after { transition: none; }
}

/* Touch has no hover, so the reveal is the tap — see the open state below. */
@media (pointer: coarse) {
  .sch-cell:hover { z-index: auto; overflow: hidden; }
  .sch-cell:hover::after { content: none; }
}

/* An opened day (tapped, or "+N more" pressed) stays open rather than depending
   on the cursor remaining inside it. */
.sch-cell.sch-cell-open { overflow: visible; min-height: 0; z-index: 31; }

.sch-out { background: var(--surface-2); }
.sch-out .sch-cellnum { color: var(--text-4); }

/* ── DAYS THAT HAVE GONE ────────────────────────────────────────────────────
   Alex: *"I like the idea that all the days have gone in the past… not just
   greyed out but somehow marked like it's complete."*

   The ground recedes and the numbers quieten, so the eye falls forward to the
   weeks he can still do something about. `--surface-3` rather than a grey wash:
   it is the same warm paper the shell already uses for recessed surfaces, so a
   fortnight of history reads as settled rather than as disabled. */
.sch-past { background: var(--surface-3); }
.sch-past .sch-cellnum { color: var(--text-4); }

/* The outcome mark beside the number: tick if everything went, black cross if
   anything did not. Sized to sit with the number rather than shout over it —
   a whole fortnight of these is meant to be a texture, not a row of alarms. */
.sch-outcome { display: inline-flex; margin-left: 5px; }
.sch-outcome svg { width: 10px; height: 10px; display: block; }
.sch-outcome-ok { color: var(--text-4); }
/* ⚠️ INK, AND FULL STRENGTH. This is the one mark on a past day that is allowed
   to survive the recession — it is the whole reason he wanted past days marked
   at all: finding the day something did not go out, at a glance, a week later. */
.sch-outcome-bad { color: var(--text); }

/* TODAY. The strongest single marker on the grid, because "where am I" is the
   first question the screen has to answer. */
.sch-cell-today { background: var(--accent-softer); box-shadow: inset 0 3px 0 var(--accent); }
.sch-cellnum {
  font-family: "Bricolage Grotesque", sans-serif; font-weight: 700; font-size: 13.5px;
  color: var(--text-2); margin-bottom: 1px; display: flex; align-items: center; gap: 6px;
}
.sch-todaytag {
  font-family: "JetBrains Mono", monospace; font-size: 8.5px;
  letter-spacing: 0.1em; color: var(--accent); font-weight: 500;
}
/* ⚠️ THE COUNT LIVES IN THE DATE ROW AND IS DELIBERATELY SMALL. As a full-width
   block button it needed 48px of a 96px row — more than the chip it was
   counting — so a laptop got one chip and a half-drawn button. Here it costs no
   vertical space at all.

   It is under the 48px touch minimum on purpose, and that is safe because it is
   a DESKTOP-ONLY control: on a phone every chip is shown and `.sch-more` is
   `display: none`. The 48px targets on this screen are the chips and the add
   button, which are what a thumb actually reaches for. */
.sch-more {
  margin-left: auto;
  display: inline-flex; align-items: center; gap: 4px;
  border: 1px solid var(--border); border-radius: 999px; padding: 1px 7px;
  font-size: 9.5px; font-weight: 700; color: var(--text-3);
  background: var(--surface-2); font-family: "JetBrains Mono", monospace;
  cursor: pointer; white-space: nowrap;
}
.sch-more:hover { background: var(--surface-3); color: var(--text-2); }
.sch-more-less { font-family: inherit; font-size: 10px; }

/* A deadline is a fact about the day, not something going out — so it is a band
   pinned to the top of the cell rather than another chip competing for the eye. */
.sch-deadline {
  display: flex; align-items: center; gap: 5px;
  background: var(--warn-soft); border-radius: 6px; padding: 3px 7px;
  font-size: 9.5px; font-weight: 700; color: var(--warn);
}
.sch-deadline svg { width: 10px; height: 10px; flex-shrink: 0; }

/* ── phone ──────────────────────────────────────────────────────────────── */

@media (max-width: 900px) {
  /* A seven-column month grid on a 390px screen gives each day 50px, which is
     narrower than the shortest useful title. So the month becomes a list of the
     days that actually have something on them — the same data, read down. */
  .sch-hrow { display: none; }
  .sch-grid { grid-template-columns: 1fr; }
  .sch-cell { min-height: 0; }
  .sch-full .sch-grid,
  .sch-full .sch-strip .sch-grid { grid-auto-rows: auto; }

  /* ⚠️ THIS RULE USED TO MATCH NOTHING. It was `.sch-cell:empty`, and a cell is
     never empty — it always contains its own date number. So the phone list was
     all forty-two days, thirty of them blank, and the thing he opened the app to
     see was somewhere near the bottom. The emptiness is now decided in the JS,
     where the day's contents are known (`sch-cell-bare`).

     A PAST day with something in it stays — that is the record. */
  .sch-month:not(.sch-strip) .sch-cell-bare:not(.sch-cell-today) { display: none; }
  /* Today stays even when it is blank — "where am I" is the first question the
     screen has to answer, and a list that starts at next Tuesday answers it
     wrongly. */
  /* ⚠️ THE STRIP KEEPS ITS BLANK DAYS. It is seven specific days, and his reason
     for wanting it is *"see where the gaps are"* — a gap you cannot see is not a
     gap. Only the month list, which is forty-two days long, drops them. */

  /* Each day is a full-width row, so it can afford its date spelled out and all
     of its chips. Nothing is clipped and nothing needs a hover to be read. */
  .sch-cellnum { font-size: 15px; }
  /* `fitCells` returns early on a phone, so nothing is ever marked clipped and
     the whole day is simply there. The count button has nothing left to count. */
  .sch-more { display: none; }

  /* ══ ONE ROW OF CHROME, NOT THREE ═══════════════════════════════════════
     ══ MEASURED, NOT INTENDED ═══════════════════════════════════════════════
     🚨 THIS BLOCK ONCE CLAIMED "291px → about 88px" AND IT WAS NEVER TRUE. The
     number was the layout I meant to write; the layout that shipped measured
     **328px** — `.cc-bar` 95 + `.sch-head` 113 + `.sch-filters` 120 — and Alex
     found it on his phone with the date wrapped over five lines.

     Every number below was taken by rendering this stylesheet in Chromium at
     390×844 against the real payload. If you change this block, re-measure the
     same way; a number in a comment is worth nothing if it came from arithmetic
     on the values you were hoping for. (CODING-STANDARDS §"The Control Centre".)

     ══ WHY IT WAS 113px ═════════════════════════════════════════════════════
     🚨 A SPECIFICITY LOSS, NOT A LAYOUT CHOICE. `.sch-today-btn { display: none }`
     is 0,1,0. `app-shell.css` carries `.cc-page .btn { display: inline-flex }`
     at 0,2,0, and this calendar is mounted INSIDE `.cc-page`. So the rule that
     was supposed to reclaim a third of the row never applied here at all — it
     applied on the standalone Social screen, which is where it got "verified".
     `.cc-page` is prefixed below so the two selectors are at equal weight and
     the later one (this file) wins.

     ⚠️ THE LESSON GENERALISES: a `display: none` that silently loses is
     indistinguishable from one that works, right up until someone screenshots
     it. Any rule this file writes against `.btn` inside the Control Centre needs
     the same prefix. */
  .sch-head { flex-wrap: nowrap; gap: 6px; align-items: center; margin-bottom: 8px; }
  .sch-nav { flex: 1 1 auto; min-width: 0; gap: 4px; }

  /* ⚠️ ONE LINE, NEVER TWO. `nowrap` is the guarantee; the short date format and
     the icon-sized arrows are what make it fit. 16 characters at 15.5px is
     ~118px, and the row has ~200px after the arrows and the switch. */
  .sch-month-label {
    font-size: 15.5px; flex: 1 1 auto; text-align: center; min-width: 0;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
    cursor: pointer; letter-spacing: -0.01em;
  }
  /* "Today" is reachable by tapping the label (wired in schedule-calendar.js,
     with role=button and keyboard support), so the separate button is redundant
     here and was costing a third of the row. ⚠️ The handler is what makes this
     safe — hiding the button without it would silently remove a control, and
     the `.cc-page` prefix is what makes the hiding actually happen. */
  .sch-today-btn,
  .cc-page .sch-today-btn { display: none; }

  /* The arrows become icon-sized: they are 44px of hit area with 32px of paint,
     which is the touch-target rule read correctly (see .sch-filter below). */
  .sch-prev, .sch-next,
  .cc-page .sch-prev, .cc-page .sch-next {
    flex: 0 0 auto; width: 32px; height: 32px; padding: 0;
    display: inline-flex; align-items: center; justify-content: center;
    border: 0; background: transparent; font-size: 17px; line-height: 1;
    position: relative;
  }
  /* The hit area, grown past the paint. */
  .sch-prev::after, .sch-next::after { content: ""; position: absolute; inset: -6px; }

  .sch-views { flex: 0 0 auto; }
  .sch-view,
  .cc-page .sch-view {
    flex: 0 0 auto; padding: 0 12px; height: 30px; font-size: 12px;
    min-height: 0; display: inline-flex; align-items: center; position: relative;
  }
  .sch-view::after { content: ""; position: absolute; inset: -7px -2px; }
  /* Both labels are always in the DOM so a resize can never leave the wrong word
     on screen; CSS picks. See the `vb` helper in schedule-calendar.js. */
  .sch-view-long { display: none; }
  .sch-view-short { display: inline; }

  /* ⚠️ THE ZONE IS A SUFFIX, NOT A CONTROL. Alex: *"you're going to have it once
     and setting the date again."* It says what the times on this screen mean,
     which is exactly the date line's job, and it costs 26px instead of 48. */
  .sch-label-tz { font-size: 9.5px; }

  .sch-week { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .sch-work-grid { grid-template-columns: 1fr; }
  .sch-tile-head { flex-wrap: wrap; }
  /* ══ THE FILTER ROW: 120px → 40px ════════════════════════════════════════
     It was the biggest block on the screen and the least use to someone who has
     just arrived: three chips at 48px each, wrapping onto two rows because the
     words would not fit, plus a waiting pill and a timezone box.

     🚨 THE 48px WAS MY OWN RULE, MISAPPLIED. `--rk-touch-target` is a minimum
     HIT AREA, not a painted height — Apple (44pt), Google (48dp) and WCAG 2.5.8
     all specify the target, and every one of them is satisfied by a 30px pill
     with padding around it. `min-height: 48px` on the chip itself turned a floor
     into a fixed height and cost 18px per chip across two rows. The `::after`
     below is the hit area, grown past the paint; the chip is 30px.

     Alex, 2026-08-26: *"The pills are really thick. Is that the standard size
     that we should be having for mobile?"* No — and that is the distinction.

     The card loses its own background too: a white card around a row of tinted
     chips is a container drawn around things that already have edges. */
  .sch-filters {
    flex-direction: row; align-items: center; gap: 8px;
    padding: 0; margin-bottom: 8px;
    background: none; border: 0; border-radius: 0;
    overflow-x: auto; overflow-y: hidden;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
  }
  .sch-filters::-webkit-scrollbar { display: none; }
  .sch-filter-row { flex-wrap: nowrap; gap: 6px; width: 100%; }

  /* ⚠️ THE WORD GOES; THE STATE STAYS. Alex: *"Surely it's Facebook, email,
     community. You don't need the words there."* Agreed — but an OFF filter
     must still LOOK off, or hiding a whole content type is invisible and the
     coach concludes nothing is scheduled. Tint, count and the greying below all
     survive losing the label; `title` and `aria-pressed` carry the rest. */
  .sch-filter {
    flex: 0 0 auto; gap: 5px; padding: 0 10px; height: 30px;
    min-height: 0; font-size: 12px; position: relative;
  }
  .sch-filter::after { content: ""; position: absolute; inset: -9px -2px; }
  .sch-flabel { display: none; }
  .sch-filter .sch-glyph svg { width: 13px; height: 13px; }
  .sch-fcount { font-size: 10.5px; font-weight: 700; color: var(--text-2); }
  /* An OFF chip is greyed AND faded — two signals, because colour alone is not
     one. This is the same rule as the state system on the grid. */
  .sch-filter:not(.sch-on) { opacity: .55; }
  .sch-filter:not(.sch-on) .sch-fcount { color: var(--text-4); }

  /* "N need you" is the last thing on the row and the only red on it. */
  .sch-waiting { flex: 0 0 auto; margin-left: auto; height: 30px; padding: 0 11px; }
  .sch-tzline { white-space: nowrap; }
}

/* ── how the Control Centre hosts it ────────────────────────────────────── */

/* Collapsed: a full-width card ABOVE the two-column grid, so it orients the
   page without displacing "what needs me". */
.cc-cal-tile { margin-bottom: 22px; }

/* Expanded: the calendar takes the workspace and the grid is not rendered at
   all — hiding it with CSS would still pay for its data and its DOM. */
.cc-cal-full { margin-bottom: 22px; }


/* ══ ADDING SOMETHING ON A DAY ══════════════════════════════════════════════
   Alex, 2026-08-26: *"when you click on a date it should give you a little
   option to create something there for that day."*

   The button is quiet until the day is hovered or focused — a plus sign in all
   42 cells at once is visual noise on a screen whose whole job is letting one
   red chip stand out. It becomes fully visible on keyboard focus too, or it
   would be a control only a mouse could find. */
.sch-add {
  margin-top: auto; align-self: stretch;
  display: flex; align-items: center; justify-content: center;
  min-height: 26px; padding: 0;
  border: 1px dashed var(--border-strong); border-radius: 7px;
  background: transparent; color: var(--text-3); cursor: pointer;
  opacity: 0; transition: opacity .12s, border-color .12s, color .12s;
}
.sch-add svg { width: 13px; height: 13px; display: block; }
.sch-cell:hover .sch-add,
.sch-cell:focus-within .sch-add { opacity: 1; }
.sch-add:hover { border-color: var(--accent); color: var(--accent); background: var(--accent-softer); }
.sch-add:focus-visible { opacity: 1; outline: 2px solid var(--accent); outline-offset: 1px; }

/* On a touch screen there is no hover, so it is simply always there — an
   affordance that only appears on hover does not exist on a phone. */
@media (pointer: coarse) {
  .sch-add { opacity: 1; min-height: var(--rk-touch-target, 48px); }
}

.sch-menu {
  position: absolute; z-index: 40; margin-top: 4px; min-width: 218px;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: 13px; box-shadow: 0 14px 40px rgba(21, 23, 43, .15);
  padding: 7px; display: flex; flex-direction: column; gap: 1px;
  text-align: left;
}
/* The cell is the positioning context so the menu hangs off the button rather
   than off the page — and it is allowed to escape the cell it belongs to. */
.sch-cell { position: relative; }
.sch-cell:has(.sch-menu) { overflow: visible; z-index: 41; }

.sch-menu-head { padding: 7px 10px 6px; display: flex; flex-direction: column; gap: 1px; }
.sch-menu-eye {
  font-family: "JetBrains Mono", monospace; font-size: 9.5px;
  letter-spacing: 0.1em; color: var(--text-3);
}
.sch-menu-when { font-family: "JetBrains Mono", monospace; font-size: 12.5px; font-weight: 700; }

.sch-menu-row {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 10px; border: none; border-radius: 9px;
  background: transparent; cursor: pointer; font-family: inherit;
  min-height: var(--rk-touch-target, 44px); width: 100%;
}
.sch-menu-row:hover { background: var(--accent-softer); }
.sch-menu-row:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
/* The same channel colour the chips use, so the menu row and the chip it will
   produce are visibly the same thing. */
.sch-menu-rail { width: 3px; height: 24px; border-radius: 2px; background: var(--sch-c); flex: none; }
.sch-menu-ico { display: inline-flex; color: var(--text-2); flex: none; }
.sch-menu-ico svg { width: 15px; height: 15px; display: block; }
.sch-menu-lab { flex: 1 1 auto; font-size: 13px; font-weight: 500; color: var(--text); }
/* ⚠️ THE ARROW IS A PROMISE, AND IT IS KEPT. Every one of these opens a NEW
   TAB; saying so before the click is what makes that acceptable rather than
   startling. */
/* `.sch-menu-out` deleted 2026-08-27 with the `↗` it styled — the menu opens the
   composer in a modal now, so there is no new tab to promise. */

/* ══ THE WEEK ARROWS THAT FLANK THE GRID ═══════════════════════════════════
   Alex, 2026-08-27: *"There needs to be a little arrow at the left of the back,
   in the front of the left, and the right of the calendar so I can easily move
   without triggering that to try and change the page, which is kind of
   irritating."*

   They sit OUTSIDE the cells rather than floating over them — the wrapper is a
   3-column grid, so a chip is never covered and a click near the edge of a day
   is never stolen by an arrow.

   ⚠️ HIDDEN ON A PHONE, on purpose. There the swipe IS the gesture (and it
   works — it is the trackpad that was broken), and 34px of chrome on each side
   of a 390px week is a real cost to the thing he is trying to read. The header
   pair stays available at every width. */
.sch-monthwrap {
  display: grid;
  grid-template-columns: 34px minmax(0, 1fr) 34px;
  align-items: stretch;
}
.sch-edge {
  border: 0; background: none; cursor: pointer; padding: 0;
  color: var(--text-4); display: flex; align-items: center; justify-content: center;
  transition: color .12s, background .12s;
  /* Full-height target: the arrow is findable anywhere down the side of the
     grid rather than only at one vertical spot. */
  align-self: stretch;
}
.sch-edge svg { width: 20px; height: 20px; display: block; }
.sch-edge:hover { color: var(--accent); background: var(--surface-2); }
.sch-edge:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }

@media (max-width: 900px) {
  .sch-monthwrap { grid-template-columns: minmax(0, 1fr); }
  .sch-edge { display: none; }
}
