/* glass-phone.css — the phone's own furniture.
 *
 * A new sheet rather than more of glass-reading.css, which is 789 of its
 * 800 lines and whose subject is the reading measure — the spread, the type
 * scale, the figures. None of that is what these rules are about: this is
 * the shelf, the bar and the opening graph on a screen too small to put two
 * things beside each other. (Round 5 named exactly this seam.)
 *
 * Everything here lives inside `@media (max-width: 900px)` — the same
 * breakpoint glass-rail.js, glass-phone.js and glass-phone-graph.js all
 * ask about, so a rule can never disagree with the state it is drawing.
 */

@media (max-width: 900px) {

/* ── the contents shelf reads as an instrument ────────────────────────
 * It was a 0.55rem muted word over a row of chips and Dan could not find
 * it. The header takes the rail's own colours and its own page count, so
 * the shelf says both what it is and how big the place is — the same two
 * facts the desk's CONTENTS tab carries. */
/* …AND IT IS THE SAME STROKE (§13). On a phone the arm runs the full width
   and turns down at its LEFT end into the chip shelf, so the header is the
   stroke rather than a muted word over a row of chips.

   ONE THICKNESS, AND IT IS THE HOUSE'S (lead, §14, on the live promote-8
   shot: "the stroke became a filled amber slab behind the whole CONTENTS row
   with an oversized outer corner sweeping down the left edge"). This sheet
   had thickened `--elbow-w` to 44 on the argument that a stroke is as thick
   as the controls it carries. Two things were wrong with that. A 44px stroke
   across a 390px screen is 11% of the viewport in one flat colour — a band,
   not a line. And `--elbow-r` IS the stroke, so thickening it took the turn
   with it: the fillet became a 44px square and the leg an 88px lobe, 88px of
   amber two strokes wide hanging beside the chips. The stroke is 24px here
   as everywhere; what the 44px rule was really about is the TAP TARGET, and
   a target is grown outside the box (the ◂ below, and `.mem-chip` before it)
   rather than by fattening the drawing. */
:root {
  --elbow-w: 24px;
  /* every control down here is one tap target tall, and the shelf is made of
     them: naming it lets the stroke be measured against the row it runs
     beside instead of against a number typed twice */
  --tap: 44px;
}
/* THE CORNER IS ONE QUARTER-ROUND (§15, on the live promote-9 shot: "the
   corner at the top-left of the shelf is a lump rather than a quarter-round of
   `--elbow-R` continuing into the leg"). It WAS a lump, and the reason is
   worth keeping: the fillet was drawn as a box with one rounded corner, and
   `border-radius` rounds a corner OFF — it does not cut a disc out. A 24x24
   box with `border-radius: 0 0 24px 0` paints the quarter DISC centred on the
   inner corner: 78% of the square, bulging into the paper. The concave fillet
   is that disc's complement, the small curved triangle hugging the corner, and
   no single border-radius can paint it.

   A border can. One element with a top and a left border of the stroke's own
   width and `border-top-left-radius: --elbow-R` is the whole turn in one
   piece: the browser draws the outer arc at R and the inner arc at R minus the
   border width — 48 and 24 — so the outer corner and the concave fillet are
   two edges of ONE quarter-round, and there is no seam between them to
   mis-colour. That is why the arm starts at x = R and the leg picks up at
   y = R: between them is the corner, and the corner is one element. */
#toc-side { padding-left: 0; padding-right: 0; }
#toc-side h3 {
  /* 0.68rem measured 10.9px, which is small type to hang a control's name on.
     The stroke is 24px and a line of this face is 1.2em, so 11.5px is what the
     stroke can carry without growing (§15: "the CONTENTS label and count
     legible on the stroke at 390x664"). */
  font-family: var(--font-display); font-size: 0.72rem; font-weight: 600;
  letter-spacing: var(--track-label); text-transform: uppercase;
  color: var(--on-amber); background: var(--amber);
  display: flex; align-items: center; gap: 0.3rem;
  /* NO GAP UNDER THE BAND. The leg is absolutely positioned, so it runs down
     beside the chips rather than under them, and a stroke-height of margin
     here is 44px of nothing above every article — measured at 390x664, it
     took the shelf from 151px to 184 and cost D-20 on every page. */
  min-height: var(--elbow-w); margin: 0 0 0 var(--elbow-R);
  padding: 0 0.7rem 0 0.4rem; position: relative;
  /* SQUARE, on all four. The arm is the straight part of the stroke; the round
     belongs to the corner element, which is the only thing that can draw both
     of its arcs. A radius here as well would be the second radius §15 refuses. */
  border-radius: 0;
}
#toc-side h3 .ph-count {
  font-family: var(--font-data); color: var(--on-amber); opacity: 0.75; letter-spacing: 0.04em;
}
/* the turn itself — one quarter-round, R outside and R minus the stroke in */
#toc-side h3::before {
  content: ""; position: absolute; left: calc(var(--elbow-R) * -1); right: auto; top: 0;
  width: var(--elbow-R); height: var(--elbow-R); box-sizing: border-box;
  background: none;
  border-top: var(--elbow-w) solid var(--amber);
  border-left: var(--elbow-w) solid var(--amber);
  border-top-left-radius: var(--elbow-R);
  border-bottom-left-radius: 0; border-top-right-radius: 0; border-bottom-right-radius: 0;
  pointer-events: none;
}
#toc-side h3::after {
  content: ""; display: block; position: absolute;
  left: calc(var(--elbow-R) * -1); right: auto; top: var(--elbow-R);
  /* THE LEG RUNS DOWN THE SHELF'S LEFT EDGE, one stroke wide, and ends in a
     cap rather than a square cut (§13). It is as long as the row it runs
     beside — one tap target and the shelf's own gap under it. It starts where
     the corner ends: `top: 100%` was right while the arm's own box turned the
     corner, and would now start the leg a stroke above the curve it continues. */
  width: var(--elbow-w); height: calc(var(--tap) + 0.4rem);
  background: var(--amber);
  border-radius: 0 0 var(--elbow-r) var(--elbow-r);
}
/* THE CHIPS ARE ON THE GROUND, and the ground starts clear of the whole turn.
   Two strokes is exactly where the corner's inner arc lands (R = 2w), so the
   first chip sits tangent to the curve rather than under it. */
#toc { padding-left: calc(var(--elbow-w) * 2); padding-right: 0.9rem; }
/* THE SHELF FOLDS, and the same control folds it. Round 6 hid the ◂ here
   because tocState refused to shut the rail below 900px — the reader could
   say "hide the contents" and be told "Contents hidden." over a shelf that
   had not moved. tocState honours their pick now, so the control comes back:
   a 44px square at the end of the shelf's own header, with the glyph a shelf
   asks for. The text stays "◂" in the markup because the DESK's control is
   the same element and the same word; only the drawing turns. */
/* …and its 44px is REACH, not drawing. `min-height: 44px` on a child of the
   arm made the arm 44px tall, which is how a stroke became a band: a flex
   line is as tall as its tallest item. The box is one stroke; the target is
   grown outside it, the way `.mem-chip` grows its own (D-29). */
#toc-side h3 #toc-shut {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: var(--elbow-w); min-height: var(--elbow-w); margin-left: auto; padding: 0;
  color: var(--on-amber); font-size: 0; line-height: 1; position: relative;
}
#toc-side h3 #toc-shut::before {
  content: ""; position: absolute; left: 50%; top: 50%;
  width: max(100%, var(--tap)); height: max(100%, var(--tap)); transform: translate(-50%, -50%);
}
#toc-side h3 #toc-shut::after { content: "\25B4"; font-size: 1rem; }
#toc-side h3 { align-items: center; }

/* ── …and the chip that stands in when the shelf is not there ──────────
 * A page can arrive with the rail displayed away (a `toc-shut` body from a
 * desk session, a pack whose rail draws nothing). The chip takes the
 * shelf's own row at the top of the stage and says the words that bring
 * the shelf back — it is never a second control beside a shelf that is
 * already on the page (glass-phone.js hides it whenever the shelf shows). */
.ph-chip-row { padding: 0.55rem 0.9rem 0; }
.ph-chip {
  display: inline-flex; align-items: center; gap: 0.35rem;
  min-height: var(--tap); padding: 0 0.85rem;
  font-family: var(--font-display); font-size: 0.68rem; font-weight: 600;
  letter-spacing: var(--track-label); text-transform: uppercase;
  color: var(--on-amber, #0b0f16); background: var(--amber);
  border: none; border-radius: var(--r-rail, 4px); cursor: pointer;
}
.ph-chip-c { font-family: var(--font-data); font-weight: 400; opacity: 0.75; }
/* ONE of them, never both. When the chip is up the shelf is not drawing rows,
   and its bare header over nothing is the second CONTENTS a reader has to
   choose between. The chip is inserted immediately before #toc-side, so the
   sibling rule needs no class and no second state to keep in step. */
#ph-toc-chip:not([hidden]) + #toc-side { display: none; }
.ph-chip:focus-visible { outline: 2px solid var(--cyan); outline-offset: 2px; }

/* ── the bar, explaining itself ───────────────────────────────────────
 * One line on a first visit, and it sits BELOW THE SHELF (§15). It was a
 * child of #omni-term, which at `data-state="narrow"` is `position: fixed` at
 * the top edge — so the row grew the fixed bar downward over the stroke and
 * hid the CONTENTS label, while the shelf under it went on reserving the
 * constant 30px a 24px bar asks for. Nothing downstream of a fixed element
 * can know it got taller, so the row leaves it: in the stage, after the
 * shelf, it takes its own height from the page and can overlap nothing.
 *
 * It is REMOVED by the first keystroke, not faded: glass-phone.js does that,
 * and there is no rule here that could leave it on screen after its lesson.
 * Its left edge is the chips' — one stroke of the elbow's leg and its turn —
 * so it reads as the shelf's own last line rather than as the page's first. */
.ph-hint {
  font-family: var(--font-body); font-size: 0.75rem; line-height: 1.35;
  color: var(--muted);
  padding: 0.15rem 0.9rem 0.55rem calc(var(--elbow-w) * 2);
}
/* THE PROMPT IS THE MENU, so it cannot be gone. Round 6 hid it to make the
   placeholder fit — measured at 375px, the lamp, the prompt "daniel gray>"
   and the TERM chip left 118px for the box and a reader saw "tap to type ·
   sa" — and with it went the only pointer path to the grammar list (§13):
   `#term-ps1` is what glass-menu.js binds the menu to.

   THE BAR STAYS 24px. That ceiling is the omni round's own (§9c, and
   glass-term.css says so in the rule), so the button cannot grow the bar and
   must not try: making the lamp and the box 44px tall pushed both out of a
   23px form and the frame showed them clipped against the top of the screen.
   What stands down is the WORD — the caret is the control, the full prompt
   is back the moment the bar is opened and on every line of the log — and
   the TARGET grows outside the box, through the same transparent ::before
   glass-term.css already grows the lamp's with. Measured: 15x21 drawn,
   44x44 to a thumb, and the placeholder gets 240px instead of 183.

   The selector matches glass-term.css's own, so it wins on cascade order
   rather than on a specificity race that a later edit there would undo. */
.omni-term[data-state="narrow"] #omni-form .ps1 {
  font-size: 0; padding: 0; min-width: 0.9rem;
  display: inline-flex; align-items: center; justify-content: center;
}
.omni-term[data-state="narrow"] #omni-form .ps1::after {
  content: "\203A"; font-family: var(--font-data); font-size: 1rem; line-height: 1;
}

/* ── the graph, in the page ───────────────────────────────────────────
 * `static`, in the flow, first inside #doc — before the masthead, so it is
 * the page's opening figure and the title follows it.
 *
 * Every float rule in constellation.css keys off `.g3d-float`, which this
 * element never has: it cannot be dragged to a corner because there is no
 * corner to drag it to. It is a figure, not a card — no frame of its own,
 * like every other figure in the flow. The canvas keeps constellation.css's
 * own `touch-action: none`, which is what hands a drag to the camera rather
 * than to the page's scroll. */
.ph-graph.viz {
  position: static; inset: auto; z-index: auto;
  display: block; width: auto; margin: 0 0 1.2rem; padding: 0;
  border: none; background: none; overflow: visible;
}
/* THE BOX HAS A WIDTH OF ITS OWN, and that is the whole trick. The renderer
 * sizes itself from `host.clientWidth` and constellation.css draws the canvas
 * at `width: 100%` of it — so a shrink-to-fit host (a flex item, an
 * inline-block) and the canvas inside it each wait for the other and settle
 * at the 180px floor. Measured: a 139x130 canvas in a 340px box.
 *
 * 76vw is chosen so the height lands where the brief asked: the engine's
 * frame is 0.72 of its width, and 0.72 x 76vw is 55vw. */
/* …AND WHAT BOUNDS IT IS A MEASUREMENT, not a fraction. This carried
   `min(76vw, 100%, 27vh)` for one round: a number adjusted by hand until
   /cassini fitted, on a sheet that cannot know how tall a headline is or
   whether the page has a strip. `GlassHero.cap()` reads the box and the
   first sentence and takes exactly the overshoot out of the sky's width
   (glass-hero.js `openings`), with the same 120px floor a picture has — so
   a page that fits keeps its opening whole and a page that does not gives up
   only what it must. The sheet is back to the brief's own 76vw. */
.ph-graph .ph-graph-in { width: min(76vw, 100%); margin: 0 auto; }
/* …and the picture inside it SCALES rather than being cropped when the cap
   bounds the host: the renderer writes the canvas's size inline, in px, from
   its own drawing buffer, so the sheet has to say `!important` to take the
   presentation back. The buffer is untouched — what changes is how big the
   same picture is drawn, which on a 2x phone costs nothing. */
.ph-graph .ph-graph-in > canvas {
  max-width: 100%; width: auto !important; height: auto !important; margin: 0 auto;
}
.ph-graph .viz-note {
  font-family: var(--font-display); font-size: 0.55rem;
  letter-spacing: var(--track-label); text-transform: uppercase;
  color: var(--muted); padding: 0 0.6rem 0.45rem; text-align: center;
}
.ph-graph .g3d-ctl { display: none; }        /* move / expand / dock: no corners here */
.ph-graph[hidden] { display: none; }
/* TWO PICTURES OF ONE NEIGHBOURHOOD IS ONE TOO MANY. On a desk the still is
   the page's opening figure and the live sky is a corner companion; on a
   phone the live one IS the opening figure, in the flow above the mast, and
   the still below it draws the same links again. So the still stands down —
   but only while the live one is actually there: fold the graph away, or let
   it fail to draw (the box is removed), and the still is the figure again.
   No class and no state: the DOM already knows whether a sky is drawn.
   ASKED OF #doc, NOT OF A SIBLING. This read `#ph-graph:not([hidden]) ~ .mast
   .hero-links` while the sky was #doc's first child and the mast its next
   sibling. §14 moves both of them — the sky after the first paragraph, the
   still with it — on every screen under 700px tall, and a combinator that
   stops matching does not fail loudly: it draws the same neighbourhood twice
   on the shortest screens there are, which are the ones the ruling is for. */
#doc:has(#ph-graph:not([hidden])) .hero-links { display: none; }

/* ── the fixed edge tab is not on the phone's paper at all ────────────
 * `#rail-tab` (ⓘ GLASS) is `position: fixed; right: 0; top: 40%` and 44px
 * wide, so 26px of every line's right-hand end passed under it as the reader
 * scrolled — the paper's own 1.1rem of right padding does not reach it.
 * Round 8 answered with a gutter: the paper's right padding became the tab's
 * own width, so the measure ended where the tab began. It worked, and it cost
 * 26px of a 390px line plus D-20 on two pages whose headline took one more
 * line for it.
 *
 * §15 is the better answer: a control that has to be paid for on every line
 * of every page does not belong on a phone's edge. The notes are a thing you
 * ask for ONCE. So below 900px the tab goes, the ask moves into the collapsed
 * bar's grammar menu ("The glass notes", glass-menu.js) where the rest of the
 * grammar already lives, and the paper takes its full width back — no gutter
 * rule here at all, so `.paper`'s own 1.1rem in the shell is the padding
 * again. `body.rail-open` still opens the panel, from the menu or from the
 * verb, so nothing was removed but the sliver. The desk keeps its tab. */
#rail-tab { display: none; }

/* The float's phone rules paid for the paper's top padding. With the graph
 * in the flow there is no overlay to pay for, and a page whose graph is
 * folded away must not keep a 22vh band where it was. */
body.g3d-right .paper, body.g3d-left .paper { padding-top: 1rem; }

}
