/* MODULE: css/bar.css — the LANDSCAPE face.
   Depends on css/tokens.css. Loaded last, after every other stylesheet, because
   §2 below deliberately overrides portrait layout rules inside one media query.

   Two halves:

     §1  .bar — the instrument itself (src/bar.js). Self-contained; it would
         render correctly in any box you gave it.
     §2  the landscape SHELL state — what the rest of the app does while the bar
         is the instrument: the chassis goes, the day-strip goes, the stage goes
         full-bleed, and the surviving controls become three floating trays that
         appear on a tap and leave again.

   THE ONE RULE, restated here because this file is where it is painted:

     --signal      a quantity you still HAVE   → it SHRINKS  (timer)
     --signal-dim  a quantity you have SPENT   → it GROWS    (clock, overtime)
     --signal-warn the last two minutes        → it SHRINKS  (timer, approach)

   Every block anchors at the LEFT wall. That is the only thing they share.
*/

/* ==================================================================== *
 * 1. THE INSTRUMENT
 * ==================================================================== */

.bar {
  position: relative;
  inline-size: 100%;
  block-size: 100%;
  overflow: hidden;
  background: var(--bg);
  /* Container queries are what let the numerals be a fraction of the FACE
     rather than of the viewport, so the instrument stays correct inside the
     Panel, a preview, or a test harness at any size. */
  container-type: size;
  /* The drag is horizontal, so the browser must not claim it for a pan. */
  touch-action: none;
  -webkit-tap-highlight-color: transparent;
  user-select: none;
  -webkit-user-select: none;
  cursor: default;
}

.bar[aria-readonly='false'] {
  cursor: ew-resize;
}

.bar:focus-visible {
  outline: 2px solid var(--signal);
  outline-offset: -4px;
}

/* THE BLOCK. Anchored left, width driven by the single --bar-p property that
   src/bar.js writes. The knockout's clip reads the SAME property (see below),
   which is what makes the two layers unable to desynchronise. */
.bar__fill {
  position: absolute;
  inset-block: 0;
  inset-inline-start: 0;
  inline-size: var(--bar-p, 100%);
  background: var(--signal);
  /* No transition by default: while the clock is live src/bar.js drives this
     every frame from the wall clock, and a transition would make the block lag
     the numerals. The settle cases tween in JS instead, which is the only way
     the value and the paint can stay in step. */
  will-change: inline-size;
}

.bar[data-kind='spent'] .bar__fill,
.bar[data-kind='hour'] .bar__fill { background: var(--signal-dim); }
.bar[data-kind='soon'] .bar__fill { background: var(--signal-warn); }


/* THE KNOCKOUT. Two registered copies of the numerals; the top one is clipped
   to the block. As the edge crosses a glyph, the glyph changes polarity
   mid-stroke — and where the break sits inside the numerals is itself a reading
   of progress.

   Not mix-blend-mode: a blend makes the painted colour depend on both layers,
   so neither half could be sampled by tests/landscape-contrast.spec.js. Two
   opaque layers keep each half independently measurable. */
.bar__digits {
  position: absolute;
  inset: 0;
  display: grid;
  place-content: center;
  justify-items: center;
  gap: 1.6cqh;
  padding-inline: 4cqw;
  pointer-events: none;
}

.bar__digits--spent {
  color: var(--ink);
}

.bar__digits--fill {
  color: var(--on-signal);
  clip-path: inset(0 calc(100% - var(--bar-p, 100%)) 0 0);
}


.bar[data-kind='spent'] .bar__digits--fill,
.bar[data-kind='hour'] .bar__digits--fill { color: var(--on-signal-dim); }
.bar[data-kind='soon'] .bar__digits--fill { color: var(--on-signal-warn); }

/* The numerals. Same type role as .t-display (PHASE4 §3) — weight 300, opsz 32,
   -0.035em, tabular — but sized against the face instead of the viewport.
   38cqh puts a ~137px cap height on a 360px-tall landscape phone. */
.bar__time {
  font-family: var(--font-num);
  font-size: 38cqh;
  font-weight: var(--wt-light);
  line-height: 0.86;
  letter-spacing: var(--tr-display);
  font-variation-settings: var(--vf-display);
  font-variant-numeric: var(--font-num-variant);
  font-feature-settings: var(--feat-num);
  white-space: nowrap;
  /* Ornament ban, made structural rather than advisory (css/type.css §2). */
  text-shadow: none;
  -webkit-text-stroke-width: 0;
  background-image: none;
}

.bar__sub {
  font-family: var(--font-sans);
  font-size: 4.2cqh;
  font-weight: var(--wt-medium);
  letter-spacing: var(--tr-label);
  text-transform: uppercase;
  white-space: nowrap;
  opacity: 0.82;
}

.bar__sub[hidden] { display: none; }

/* THE SUB-LINE IS CHROME. "Just the clock and the colour block" means the
   numerals and the gauge — an end-time caption is a third thing. It leaves and
   returns with the trays, and it keeps its box either way so the numerals do
   not shift when it goes. */
@media (orientation: landscape) and (max-height: 560px) {
  /* THE SUB-LINE BELONGS TO THE RESTING FACE, NOT THE CHROME.
     This was inverted: the end time appeared only while the chrome was up —
     which is precisely when the transport tray rises into that space and covers
     it. The two were fighting for one band by construction.

     Right way round: at rest you get the numerals AND when this lands, which is
     the whole anti-time-blindness point. Tap for controls and the caption steps
     aside to make room for the tray. Nothing overlaps in either state. */
  /* The delay is the fix for the hand-off glitch — see the note beside the
     numerals' lift below. It lives on the RESTING state so it applies coming
     BACK from awake, and not on the way in. */
  .bar__sub { opacity: 0.82; transition: opacity var(--dur-fast) var(--ease-out) var(--dur-med); }
  [data-face-awake='true'] .bar__sub { opacity: 0; }
}

/* src/wear.js owns the patina; this file owns the surface it lands on. */
.bar__wear {
  position: absolute;
  inset: 0;
  pointer-events: none;
}

/* A tighter face gives its content room by shrinking the numerals rather than by
   clipping anything. The threshold is 460px, not 340: EVERY landscape phone is
   under 460, and at 38cqh the numerals ran into the transport tray on all of
   them. The tray is ~110px because a touch target cannot be smaller, so the
   reading is what yields. */
@container (max-height: 460px) {
  .bar__time { font-size: 34cqh; }
  .bar__sub { font-size: 5cqh; }
}

@media (prefers-reduced-motion: reduce) {
  .bar__fill { transition: none !important; }
}

/* ==================================================================== *
 * 2. THE LANDSCAPE SHELL
 *
 * Scoped to the same query the retired blocks used, so there is exactly one
 * definition of "this is a landscape phone" in the codebase.
 * ==================================================================== */

@media (orientation: landscape) and (max-height: 560px) {
  html body {
    /* THE DAY STRIP'S HEIGHT, declared once and read twice — the strip is sized
       to it and the transport clears it by it. Anything that needs to sit above
       the strip reads this, so nothing has to guess. Measured content is 42px;
       44 leaves the micro type two pixels of headroom. */
    --bar-daystrip: 44px;
  }

  /* The face is the whole screen. Everything that framed it is decoration in a
     surface whose entire job is to be looked at from across a room. */
  html body .tt-timer__meta,
  /* The session label stays off the face on purpose: a text field on a
     landscape phone summons a keyboard that eats the whole screen. It is in the
     Panel, which opens over landscape unchanged. */
  html body .tt-timer__task,
  html body .tt-timer__stepper,
  /* Clock mode prints the wall time INSIDE the block now (src/bar.js gets it via
     the `text` field), so the analogue hands, the digital line and the date
     would each be a second, disagreeing copy of the same reading. */
  html body .tt-clock__hands,
  html body .tt-clock__date,
  html body .tt-clock__day,
  /* The chassis itself survives as a box that isn't there (below) — but its
     nameplate and grille are pure decoration on a surface whose whole job is to
     be read from across a room. */
  html body .brand,
  html body .chassis__grille {
    display: none !important;
  }

  /* THE CHASSIS BECOMES NOTHING, NOT HIDDEN.
     `display: none` on the chassis would take the mode keys and the tool keys
     down with it — a hidden parent removes the entire subtree, and no amount of
     `display: flex !important` on a child opts back in. `display: contents`
     deletes the chassis BOX while leaving its children rendered, which is
     exactly what is wanted: the panel is gone, the keys it carried survive as
     free-floating trays. */
  html body .chassis {
    display: contents !important;
  }

  /* WHY `html body` AND `!important`.
     css/controls.css sizes the instrument inside `@media (max-width: 74.999rem)`
     with `inline-size: var(--instr) !important` — and a landscape phone at 932px
     matches that query. A plain `.tt-timer__stage` here loses to it no matter
     what order the stylesheets load in, so the escalation is not decoration: it
     is the minimum that wins. `html body` is the same device css/parts.css
     already uses for exactly this purpose, so this file is not inventing an
     idiom, it is following one.

     The moment those --instr blocks learn to exclude landscape, every
     `!important` below can go. */

  html body .app-shell {
    display: block !important;
    block-size: 100svh !important;
    padding: 0 !important;
    margin: 0 !important;
    max-inline-size: none !important;
    border-radius: 0;
    box-shadow: none;
    background: var(--bg);
  }

  html body .app-stage,
  html body .mode-panel,
  html body .tt-timer,
  html body .tt-clock {
    display: block !important;
    block-size: 100% !important;
    inline-size: 100% !important;
    max-inline-size: none !important;
    padding: 0 !important;
    margin: 0 !important;
    gap: 0 !important;
    overflow: hidden !important;
  }

  html body .tt-timer__stage,
  html body .tt-clock__stage {
    display: block !important;
    block-size: 100% !important;
    inline-size: 100% !important;
    max-inline-size: none !important;
    padding: 0 !important;
    margin: 0 !important;
  }

  html body .tt-timer__dial,
  html body .tt-clock__dial {
    display: block !important;
    block-size: 100% !important;
    inline-size: 100% !important;
    max-inline-size: none !important;
    padding: 0 !important;
    margin: 0 !important;
    aspect-ratio: auto !important;
    flex: 1 1 auto !important;
  }

  /* The readout is now painted INSIDE the instrument, knocked out of the block.
     The portrait LCD slab would be a second, disagreeing copy of the same
     number — so it leaves the layout but stays in the accessibility tree,
     because it is the element carrying role="timer". */
  html body .tt-timer__readout,
  html body .tt-clock__digital {
    position: absolute !important;
    inline-size: 1px !important;
    block-size: 1px !important;
    max-inline-size: none !important;
    padding: 0 !important;
    margin: -1px !important;
    overflow: hidden !important;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
    background: none;
    box-shadow: none;
  }

  /* ---------------------------------------------------------------- 2.1 trays
     THE CHROME STRADDLES THE COLOUR BREAK. Bare caps and legends sitting
     directly on the face would each need knocking out — and worse, the signal
     START key disappears into the signal block entirely.

     A full scrim was tried and rejected: it kills the gauge. Gradient bands were
     tried and rejected: they eat half the height. A tray is what the reference
     object actually has, it gives every control ONE predictable ground, and the
     block stays visible around all three. */
  html body .chassis__tools,
  html body .modes,
  html body .tt-timer__legend,
  html body .tt-timer__transport {
    position: fixed;
    z-index: 5;
    display: flex;
    align-items: flex-start;
    gap: var(--space-3);
    background: var(--bg);
    border-radius: var(--radius-l);
    padding: var(--space-3) var(--space-4);
    box-shadow: 0 0 0 1px var(--hairline), 0 6px 18px -8px rgb(0 0 0 / 0.34);
    inline-size: auto;
    max-inline-size: none;
    margin: 0;
    /* The whole chrome layer is one thing that appears and leaves together. */
    opacity: 0;
    visibility: hidden;
    transition: opacity var(--dur-med) var(--ease-out), visibility 0s linear var(--dur-med);
  }

  /* The strip keeps its portrait shape and direction exactly. It is a DIFFERENT
     METER from the gauge above it — the waking day, not the hour — so making
     the two point the same way would be a coincidence dressed as a rule. */

  /* Landscape has no chassis, so the mode switcher and the tool keys become
     free-floating trays pinned to the safe area rather than children of a bar. */
  html body .modes {
    display: flex !important; /* .chassis is display:none; its children are not */
    inset-block-start: calc(env(safe-area-inset-top, 0px) + var(--space-3));
    inset-inline-start: calc(env(safe-area-inset-left, 0px) + var(--space-3));
  }

  html body .chassis__tools {
    display: flex !important;
    inset-block-start: calc(env(safe-area-inset-top, 0px) + var(--space-3));
    inset-inline-end: calc(env(safe-area-inset-right, 0px) + var(--space-3));
  }

  /* THE FACE SELECTOR. It was hidden in the first build and the Panel never
     gained it, so "custom" — the whole point of a timer that is not 60 minutes —
     was unreachable in landscape. Top-centre: the only free edge, and it sits
     with the mode keys rather than with the transport, because it decides what
     the face MEANS rather than what the clock is doing. */
  html body .tt-timer__legend {
    position: fixed !important;
    inset-block-start: calc(env(safe-area-inset-top, 0px) + var(--space-3));
    inset-inline-start: 50%;
    translate: -50% 0;
    align-items: center;
    justify-content: center;
    border-block-start: 0;
  }

  /* THE TRANSPORT CLEARS THE DAY STRIP, and clears it by a DECLARED amount.
     This previously read `var(--bar-daystrip, 30px)` against a token that was
     never defined anywhere, so it always took the 30px fallback while the strip
     actually measured 42px. The transport sat 12px too low and the strip sliced
     the bottom 6px off every key legend — "reset", "start pause", "+1", "+5"
     were all cut in half. The token is real now (top of this block) and the
     strip is sized to the same value, so the two cannot drift apart. */
  html body .tt-timer__transport {
    position: fixed !important;
    /* !important because css/controls.css reaches this element through its own
       !important layer (APP.md §5 item 4: ~1,200 of them, later sections
       overriding earlier). Without it the offset parses, matches, and is still
       discarded — measured `bottom: 0px` against a declared 52px. Escalating is
       the idiom this whole file already uses to beat that layer; it can come
       out the day those sections do. */
    inset-block-end: calc(var(--bar-daystrip) + env(safe-area-inset-bottom, 0px) + var(--space-2)) !important;
    inset-block-start: auto !important;
    inset-inline-start: 50%;
    translate: -50% 0;
    border-block-start: 0;
  }

  /* THE DAY STRIP, back. It is the one piece of chrome that is not a control —
     it is the same reading the gauge gives, over a longer clock — so it keeps
     its portrait shape (one thin full-width bar, one line of type) instead of
     becoming a tray. Pinned to the bottom edge, hidden and shown with
     everything else. */
  html body .day-strip {
    position: fixed !important;
    z-index: 5;
    inset-inline: 0;
    inset-block-end: 0;
    /* min, not a fixed height: if the micro type ever wraps the strip may grow,
       and clipping the reading would be worse than the gap changing. The
       regression test below asserts the transport still clears it either way. */
    min-block-size: calc(var(--bar-daystrip) + env(safe-area-inset-bottom, 0px));
    margin: 0 !important;
    padding: var(--space-1) calc(env(safe-area-inset-left, 0px) + var(--space-4))
             calc(env(safe-area-inset-bottom, 0px) + var(--space-1))
             calc(env(safe-area-inset-right, 0px) + var(--space-4));
    background: var(--bg);
    box-shadow: 0 -1px 0 var(--hairline);
    opacity: 0;
    visibility: hidden;
    transition: opacity var(--dur-med) var(--ease-out), visibility 0s linear var(--dur-med);
  }

  /* The transport's own edge flute is a chassis detail; a floating tray has no
     panel edge to flute. */
  .tt-timer__transport.m-edge-flute::before,
  .tt-timer__transport.m-edge-flute::after {
    display: none;
  }

  /* AWAKE. Set by src/instrument.js on the shell for 4s after a tap, and forced
     by :focus-within so Tab always reaches the controls and nothing is hidden
     from assistive technology. */
  [data-face-awake='true'] .chassis__tools,
  [data-face-awake='true'] .modes,
  [data-face-awake='true'] .tt-timer__legend,
  [data-face-awake='true'] .tt-timer__transport,
  [data-face-awake='true'] .day-strip,
  .chassis__tools:focus-within,
  .modes:focus-within,
  .tt-timer__legend:focus-within,
  .tt-timer__transport:focus-within,
  .day-strip:focus-within {
    opacity: 1;
    visibility: visible;
    transition: opacity var(--dur-fast) var(--ease-out), visibility 0s;
  }

  /* WHILE THE CONTROLS ARE UP, THE READING GIVES WAY.
     Add it up on the smallest landscape phone (740x360): top trays ~110px,
     transport ~110px, day strip 44px. That is 264px of chrome, and a touch
     target cannot shrink, so full-size numerals simply do not fit between them —
     lifting them only traded the transport collision for a face-tray one.

     So the numerals shrink while the chrome is up. That is the right thing to
     give: at rest they are 34cqh and readable across a room, which is the whole
     point of the face; while you are reaching for a key you are operating it
     from arm's length and 22cqh is more than enough. The small lift re-centres
     them in what is left, because the bottom chrome is heavier than the top. */
  [data-face-awake='true'] .bar__time {
    font-size: 22cqh;
  }
  [data-face-awake='true'] .bar__digits {
    transform: translateY(-9cqh);
  }

  /* THE HAND-OFF. Tapping the chrome away used to produce a visibly broken
     frame for a quarter of a second: the trays stay painted for --dur-med
     while they fade, but the numerals snapped back to full size instantly and
     the end time faded straight back in, so both reflowed INTO a tray that was
     still on screen — numerals 15px into it, caption 54px under it.

     Everything that grows on the way back now waits exactly as long as the
     trays take to leave. The delays are declared on the RESTING state, which is
     what makes them apply on the return only; going the other way the trays
     need the space immediately, so awake cancels every delay. */
  .bar__time {
    transition: font-size var(--dur-fast) var(--ease-out) var(--dur-med);
  }
  .bar__digits {
    transition: transform var(--dur-med) var(--ease-out) var(--dur-med);
  }
  [data-face-awake='true'] .bar__time,
  [data-face-awake='true'] .bar__sub,
  [data-face-awake='true'] .bar__digits {
    transition-delay: 0s;
  }


  /* Focus mode already means "nothing but the instrument", which is what
     landscape is. The escape hatch stays, on top of everything. */
  .focus-exit {
    z-index: 6;
  }

  @media (prefers-reduced-motion: reduce) {
    .chassis__tools,
    .modes,
    .tt-timer__legend,
    .tt-timer__transport,
    .day-strip,
    .bar__sub,
    .bar__digits {
      transition: none !important;
    }
  }
}
