/* =============================================================================
   07-tiles.css — "First Steps in OpenUSD", layout v2: the tiling layer.

   WHY THIS FILE EXISTS
   v1 (02-layout.css) widened the shell to 1560px but the reader still met ONE
   column of running prose with a figure parked beside it (.duo). The extra
   width went to pictures, not to information. This file makes the TEXT modular:
   text tiles sit beside figure tiles sit beside fact tiles, on a shared grid.

   Owns:      .mosaic + .t tile types + span modifiers, .cols, .abstract,
              .keys, .takeaway, .steps, .check, .note (3 tones), .subhead.
   Does NOT own: anything in 02-layout.css (.duo .aside .wide .facts .versus
              .reel .asks .ledger .plates .pane .tile .card .figc) — those stay
              exactly as they are. Nothing here restyles them.
   Depends on: 02-layout.css loaded FIRST (palette tokens, --measure, --gap,
              --gut, --r, the global measure guard, pre/code overflow rules).
              Every token used below is defined there; none is redefined here.

   HOUSE RULE HONOURED THROUGHOUT: restraint in borders and fills. A tile is a
   grid cell with a hairline above it, not a box. Only tiles that genuinely need
   a container to be legible (code, steps) get a fill. See the ragged-bottom
   note at the top of the .mosaic block for why that is load-bearing, not taste.
   ============================================================================= */

:root{
  /* Tiling tokens. Deliberately few — everything else reuses v1's scale. */
  --tgap:clamp(1.05rem,1.7vw,2.1rem);   /* column gap between tiles          */
  --tgap-y:clamp(1.15rem,1.5vw,1.8rem); /* row gap; slightly > column gap so   */
                                        /* rows read as rows, not as a mesh    */
  --tpad:.72rem;                        /* the shared top inset every tile has;
                                           it is what makes filled and unfilled
                                           tiles align on their first baseline  */
  --tpadx:.85rem;                       /* side padding of FILLED tiles only    */
}


/* =============================================================================
   PATTERN A — .mosaic : the headline pattern. Tiled information.
   Use when: a section has 4+ distinct units (a definition, a diagram, a number,
             a code sample, a caution) that are peers, not a linear argument.
   Do not use when: the content is one continuous argument — that is .cols, or
             a .duo. A mosaic of three tiles is not a mosaic, it is a .facts row.

   --- THE RAGGED-BOTTOM STRATEGY (read before changing anything below) -------
   Rejected: CSS masonry (not reliably available), grid-auto-flow:dense (it
   reorders tiles visually away from DOM order, which is exactly what we may not
   do), column-count for the whole mosaic (kills side-by-side figure+text and
   fragments tiles across columns).
   Chosen: a plain explicit grid with the DEFAULT align-items:stretch, plus the
   rule that MOST TILES HAVE NO FILL AND NO BORDER — only a 1px rule along their
   top edge. Consequences:
     · Tile TOPS align on a shared horizontal rule, row by row. Top alignment is
       what the eye actually reads as "tidy"; bottom alignment is not.
     · A short tile beside a long one produces empty paper, not a short box next
       to a tall box. There is no ragged bottom to see, because there is no
       bottom edge drawn.
     · Filled tiles (.t--code, .step) DO stretch to the row height, so where a
       box exists its bottom does line up with its rowmates' boxes.
   The whole design therefore trades "boxes of equal height" for "no boxes",
   which is also the cheaper answer to "not heavy or over-designed".
   ---------------------------------------------------------------------------
   Track count: 4 ≥1440 · 3 1120–1439 · 2 700–1119 · 1 ≤699. Fixed counts, not
   auto-fit, because --w2/--w3 are meaningless unless the column count is known.
   ============================================================================= */
.mosaic{display:grid;margin:0 0 1.6rem;
        grid-template-columns:repeat(4,minmax(0,1fr));
        column-gap:var(--tgap);row-gap:var(--tgap-y);
        align-items:stretch}
.mosaic > *{min-width:0}                 /* permit overflow; escapes are below */

/* .t — the tile itself. Everything a tile shares: the top rule, the top inset,
   the vertical rhythm, and the overflow escapes that make min-width:0 safe. */
.t{min-width:0;display:flex;flex-direction:column;
   border-top:1px solid var(--rule);padding-top:var(--tpad);
   overflow-wrap:break-word}            /* ESCAPE 1: a bare /World/Foo/Bar wraps */
.t > *{margin-top:0}
.t > * + *{margin-top:.5rem}
.t > :last-child{margin-bottom:0}
.t pre{overflow-x:auto;max-width:100%}  /* ESCAPE 2: code scrolls in its tile  */

/* .t h4 — the tile eyebrow. --ink2 not --ink3: see the contrast note in
   07-tiles-notes.md. Same shape as v1's .ptitle so the page stays one voice. */
.t > h4{font-family:var(--sans);font-size:.665rem;font-weight:600;letter-spacing:.09em;
        text-transform:uppercase;color:var(--ink2);margin:0 0 .1rem;max-width:none}
.t > h4 + *{margin-top:.35rem}

/* --- tile types ---------------------------------------------------------- */

/* .t--text : prose. ONE idea, ~70 words max. The workhorse of the mosaic and
   the whole point of the file — this is the tile that stops text being a river.
   Unfilled by design. */
.t--text p{font-size:.94rem;line-height:1.62;color:var(--ink)}
.t--text p + p{margin-top:.5rem}

/* .t--fig : one image or diagram with a .figc caption. Unfilled; the image's own
   border is the only edge. Add .t--h2 when the figure deserves height. */
.t--fig{margin:0}
.t--fig > .frame{background:var(--sunk);border:1px solid var(--rule);border-radius:var(--r);
                 aspect-ratio:4/3;display:flex;align-items:center;justify-content:center;
                 overflow:hidden}
.t--fig > .frame > img,.t--fig > .frame > svg{width:100%;height:100%;object-fit:cover;display:block}
.t--fig > img{border:1px solid var(--rule);border-radius:var(--r);display:block;width:100%}
.t--fig > figcaption,.t--fig > .figc{margin-top:.45rem}

/* .t--code : a code sample. The ONE tile type that gets a fill, because code
   needs a background to read as code. Stretches to the row height. It takes
   the code plate rather than --card — see the --code tokens in the spine —
   so a listing reads the same whether it stands alone or sits in a mosaic. */
.t--code{background:var(--code,var(--card));border:1px solid var(--coderule,var(--rule));
         border-radius:var(--r);
         border-top-color:var(--coderule,var(--rule));padding:var(--tpad) var(--tpadx) .78rem;
         /* The tile IS the plate, so everything in it inherits plate ink —
            the listing, its heading and the sentence under it. */
         color:var(--codeink,var(--ink))}
.t--code > h4{color:var(--codedim,var(--ink2))}
.t--code > p,.t--code .figc,.t--code figcaption{color:var(--codeink2,var(--ink2))}
/* The spine styles `.sect pre` with its own background, border, radius and
   padding. Inside a tile that already IS that plate, those draw a box inside a
   box — invisible while both were --card, obvious now they are not. Written
   with `.sect` in front so it outranks `.sect pre` (0,1,1) on specificity;
   equal specificity would hand it to whichever sheet loaded last, and the
   spine's inline <style> always loads last. */
.sect .t--code pre{background:none;border:0;padding:0;margin:0;max-width:100%;
             color:var(--codeink,var(--ink))}

/* .t--fact : one value + one clause. Glanceable, never readable. Unfilled —
   v1's .facts .tile is the boxed version; inside a mosaic the box is noise. */
.t--fact > b{font-family:var(--mono);font-size:1.5rem;line-height:1.15;color:var(--acctxt);
             font-weight:700;letter-spacing:-.01em;overflow-wrap:anywhere;display:block}
.t--fact > span{display:block;font-family:var(--sans);font-size:.79rem;line-height:1.45;
                color:var(--ink2);margin-top:.3rem}

/* .t--quote : the sentence to remember, in the middle of the grid. Its top rule
   goes accent instead of hairline — the only colour change in the whole grid. */
.t--quote{border-top:2px solid var(--acc)}
.t--quote > p{font-family:var(--serif);font-size:1.04rem;line-height:1.5;color:var(--ink);
              max-width:none;margin:0}
.t--quote > cite{display:block;margin-top:.45rem;font-style:normal;font-family:var(--sans);
                 font-size:.7rem;letter-spacing:.06em;text-transform:uppercase;color:var(--ink2)}

/* --- span modifiers ------------------------------------------------------
   .t--w2 / .t--w3 / .t--h2. Aliases (.t.w2 etc.) are included because VOCAB-v2
   writes them bare as "--w2" and a content agent may guess either form.
   A span larger than the explicit grid CREATES IMPLICIT COLUMNS and overflows
   the page — so every span is reset explicitly at every narrower breakpoint. */
.t--w2,.t.w2{grid-column:span 2}
.t--w3,.t.w3{grid-column:span 3}
.t--h2,.t.h2{grid-row:span 2}
.t--h2 > .frame{aspect-ratio:auto;flex:1 1 auto;min-height:13rem}

/* A --w2 TEXT tile would produce ~95ch, far past the 70ch rule. Flow it in two
   internal columns instead; the heading spans both. Only put a --w2 on a text
   tile that has 3+ paragraphs — with one paragraph this looks like a mistake. */
.t--text.t--w2,.t--text.t--w3{columns:2;column-gap:var(--tgap);display:block}
.t--text.t--w3{columns:3}
.t--text.t--w2 > h4,.t--text.t--w3 > h4{column-span:all}
.t--text.t--w2 p,.t--text.t--w3 p{max-width:none;orphans:2;widows:2}


/* =============================================================================
   PATTERN B — .cols : multi-column running text.
   Use when: prose is genuinely linear but short (≤ ~180 words) — an argument
             that must be read in order but does not deserve a full-height river.
   Do not use when: it contains a figure, a pre, a heading, or anything the
             reader must find again. Multicol fragments content across columns;
             nothing findable may live inside it.
   ============================================================================= */
.cols{column-count:2;column-gap:var(--tgap);column-fill:balance;
      max-width:min(100%,104ch);margin:0 0 1.5rem}
.cols--3{column-count:3;max-width:min(100%,150ch)}
.cols > *{max-width:none}                /* the column already limits measure  */
.cols p{margin:0 0 .6rem;font-size:.95rem;line-height:1.62;
        orphans:3;widows:3}              /* no 1–2 line stub at a column break */
.cols > :first-child{margin-top:0}
.cols p:last-child{margin-bottom:0}
/* column-fill:balance is the default in a non-fragmented context, but it is
   stated because it is the whole defence against a near-empty last column:
   the browser equalises column heights rather than filling column 1 to the
   element height. The 104ch cap keeps each column near 50ch at shell width. */


/* =============================================================================
   PATTERN C — .abstract : the scan layer at the top of a chapter.
   Use when: exactly once, first thing in a chapter. One line per section.
   Do not use when: mid-chapter (that is .subhead + .keys), or with fewer than
             four sections — a three-item list is not worth a scan layer.
   ============================================================================= */
.abstract{background:var(--card);border:1px solid var(--rule);border-top:3px solid var(--acc);
          border-radius:var(--r);padding:.85rem 1rem 1rem;margin:0 0 1.8rem}
.abstract__h{margin:0 0 .6rem;max-width:none;font-family:var(--sans);font-size:.645rem;
             font-weight:700;letter-spacing:.11em;text-transform:uppercase;color:var(--acctxt)}
.abstract__l{list-style:none;margin:0;padding:0;counter-reset:abs;
             display:grid;column-gap:var(--tgap);row-gap:.1rem;
             grid-template-columns:repeat(auto-fit,minmax(min(100%,21rem),1fr))}
.abstract__l > li{min-width:0;margin:0;max-width:none;counter-increment:abs}
.abstract__l a{display:grid;grid-template-columns:1.6rem minmax(0,1fr);align-items:baseline;
               gap:.15rem .1rem;padding:.32rem .3rem .32rem 0;border-radius:3px;
               text-decoration:none;color:var(--ink);border-top:1px solid var(--rule)}
.abstract__l > li:first-child a{border-top:0}
.abstract__l a::before{content:counter(abs,decimal-leading-zero);grid-row:span 2;
                       font-family:var(--mono);font-size:.72rem;color:var(--ink2)}
.abstract__l b{font-family:var(--sans);font-size:.87rem;font-weight:600;line-height:1.35}
.abstract__l span{font-family:var(--sans);font-size:.755rem;line-height:1.4;color:var(--ink2);
                  overflow-wrap:anywhere}
.abstract__l a:hover b,.abstract__l a:focus-visible b{color:var(--acctxt)}
.abstract__l a:hover{background:var(--wash)}
.abstract__l a:focus-visible{outline:2px solid var(--acc);outline-offset:1px}
/* On a 2-column abstract the columns run down-then-across visually only because
   grid fills row-wise; DOM order IS reading order, so a screen reader hears the
   sections in chapter order. No `order`, no dense packing, anywhere in here. */


/* =============================================================================
   PATTERN D — .keys : key points, scannable.
   Use when: a paragraph is secretly a list of 3–6 parallel points. Each item is
             a bold lead phrase plus one clause.
   Do not use when: items need more than ~22 words, or are not parallel. That is
             .t--text tiles in a .mosaic.
   NOTE: implemented as auto-fit, so it is 3-up at full shell and 2-up from
   ~1050–1400px. A literal fixed 2-up would give a 91ch line at 1560, which
   breaks the ≤70ch rule stated in the same vocabulary file. See notes.
   ============================================================================= */
.keys{list-style:none;margin:0 0 1.5rem;padding:0;display:grid;align-items:start;
      column-gap:calc(var(--tgap) * 1.25);row-gap:.1rem;
      grid-template-columns:repeat(auto-fit,minmax(min(100%,25rem),1fr))}
.keys > li{min-width:0;max-width:none;margin:0;font-size:.9rem;line-height:1.55;
           color:var(--ink2);padding:.5rem 0 .55rem 1.05rem;position:relative;
           border-top:1px solid var(--rule);overflow-wrap:break-word}
.keys > li::before{content:"";position:absolute;left:0;top:1.02em;
                   width:.5rem;height:1px;background:var(--rule2)}
.keys > li > b{color:var(--ink);font-weight:650}
.keys > li > b::after{content:" \2014 ";color:var(--ink3);font-weight:400}


/* =============================================================================
   PATTERN E — .takeaway : the one thing to remember from a section.
   Use when: once per section, at its end or beside its opening. One sentence.
   Do not use when: there are two of them. Two takeaways is zero takeaways.
   ============================================================================= */
.takeaway{margin:1.1rem 0 1.5rem;padding:.15rem 0 .2rem .9rem;
          border-left:3px solid var(--acc);
          font-family:var(--serif);font-size:1.06rem;line-height:1.5;color:var(--ink);
          max-width:var(--measure)}
.takeaway em{font-style:italic;color:var(--acctxt)}
.mosaic .takeaway{margin:0;max-width:none}   /* as a tile it is already narrow */


/* =============================================================================
   PATTERN F — .steps : numbered procedure tiles.
   Use when: an install or setup procedure where each step has a command and a
             "you should see" confirmation. 2-up at shell width.
   Do not use when: the steps are one line each (that is an <ol>), or when order
             does not matter (that is a .mosaic).
   Filled + stretched: these DO get boxes, because a procedure needs to show
   where one step stops and the next begins.
   ============================================================================= */
.steps{list-style:none;margin:0 0 1.6rem;padding:0;counter-reset:step;
       display:grid;column-gap:var(--tgap);row-gap:var(--tgap-y);align-items:stretch;
       grid-template-columns:repeat(auto-fit,minmax(min(100%,30rem),1fr))}
.step{min-width:0;max-width:none;margin:0;counter-increment:step;
      background:var(--card);border:1px solid var(--rule);border-radius:var(--r);
      padding:.7rem var(--tpadx) .8rem 2.9rem;position:relative;overflow-wrap:break-word}
.step::before{content:counter(step);position:absolute;left:.85rem;top:.62rem;
              font-family:var(--mono);font-size:1.05rem;font-weight:700;color:var(--acc);
              line-height:1.2}
.step > h4{margin:0 0 .45rem;max-width:none;font-family:var(--sans);font-size:.92rem;
           font-weight:650;line-height:1.3;color:var(--ink)}
.step > p{font-size:.9rem;line-height:1.55;color:var(--ink2);margin:0 0 .5rem;max-width:none}
.step > pre{overflow-x:auto;max-width:100%;background:var(--code,var(--sunk));
            color:var(--codeink,var(--ink));border:1px solid var(--coderule,var(--rule));
            border-radius:4px;padding:.5rem .6rem;margin:0 0 .5rem}
.step > :last-child{margin-bottom:0}
/* .expect — the confirmation line. Sans, small, accent tick drawn in CSS so it
   survives a missing emoji font and is not announced as content. */
.expect{display:flex;gap:.42rem;align-items:flex-start;margin:.5rem 0 0;max-width:none;
        font-family:var(--sans);font-size:.79rem;line-height:1.45;color:var(--acctxt)}
.expect::before{content:"";flex:0 0 auto;width:.42rem;height:.72rem;margin-top:.12rem;
                border:solid var(--acc);border-width:0 2px 2px 0;transform:rotate(38deg)}


/* =============================================================================
   PATTERN G — .check : prerequisite checklist with a "how do I know" test.
   Use when: before a procedure. Every item MUST carry a verifiable test —
             that is the difference between .check and .keys.
   Do not use when: there is no way to test the item. Then it is a .keys point.
   ============================================================================= */
.check{list-style:none;margin:0 0 1.6rem;padding:0;display:grid;align-items:start;
       column-gap:calc(var(--tgap) * 1.25);row-gap:.1rem;
       grid-template-columns:repeat(auto-fit,minmax(min(100%,24rem),1fr))}
.check > li{min-width:0;max-width:none;margin:0;padding:.55rem 0 .6rem 1.55rem;
            position:relative;border-top:1px solid var(--rule);overflow-wrap:break-word}
.check > li::before{content:"";position:absolute;left:0;top:.78rem;
                    width:.72rem;height:.72rem;border:1.5px solid var(--rule2);border-radius:2px}
.check > li > b{display:block;font-family:var(--sans);font-size:.875rem;font-weight:650;
                color:var(--ink);line-height:1.35;overflow-wrap:anywhere}
.check > li > span{display:block;margin-top:.15rem;font-family:var(--sans);font-size:.795rem;
                   line-height:1.5;color:var(--ink2)}


/* =============================================================================
   PATTERN H — .note : small inline callouts, three tones.
   Use when: one or two sentences that qualify the thing next to them.
   Do not use when: it is a whole paragraph of argument, or when three notes
             stack up — three notes means the prose above them is wrong.
   Tones are distinguished by SHAPE as well as colour (solid accent / solid flag
   / dashed neutral), so they still read apart in greyscale and for colour-blind
   readers. The ::before label is real text and IS announced by screen readers,
   which is intended: "Unverified —" must be heard, not just seen.
   ============================================================================= */
.note{margin:.9rem 0 1.1rem;padding:.5rem .8rem;border-left:3px solid var(--rule2);
      border-radius:0 3px 3px 0;background:var(--sunk);
      font-family:var(--sans);font-size:.85rem;line-height:1.55;color:var(--ink2);
      max-width:var(--measure);overflow-wrap:break-word}
.note::before{font-weight:700;font-size:.645rem;letter-spacing:.1em;text-transform:uppercase;
              margin-right:.5rem}
.note--tip{background:var(--wash);border-left-color:var(--acc);border-left-style:solid;color:var(--ink2)}
.note--tip::before{content:"Tip ";color:var(--acctxt)}
.note--warn{background:var(--flagwash);border-left-color:var(--flagrule);border-left-style:solid;color:var(--ink2)}
.note--warn::before{content:"Caution ";color:var(--flag)}
.note--unverified{background:var(--sunk);border-left:3px dashed var(--rule2);color:var(--ink2)}
.note--unverified::before{content:"Unverified ";color:var(--ink2)}
.note--unverified em{font-style:italic}
.mosaic .note{margin:0;max-width:none}


/* =============================================================================
   PATTERN I — .subhead : a labelled break inside a long section.
   Use when: a section runs past ~2 screens and splits into named parts.
   Do not use when: it is really a new section (give it its own h2 and id so the
             rail and .abstract can see it).
   Full shell width on purpose: it is the horizontal line that separates one
   mosaic from the next.
   ============================================================================= */
/* Selector list, not one selector: the spine's inline `.sect h3 { max-width:66ch }`
   is (0,1,1) and would otherwise beat a bare `.subhead` (0,1,0). */
.subhead,
.sect h3.subhead{display:flex;align-items:center;gap:.85rem;max-width:none;
         margin:2.1rem 0 1rem;font-family:var(--sans);font-size:.72rem;font-weight:700;
         letter-spacing:.12em;text-transform:uppercase;color:var(--ink2)}
.subhead::after{content:"";flex:1 1 auto;height:1px;background:var(--rule)}
.sect > .subhead:first-child{margin-top:0}


/* =============================================================================
   RESPONSIVE — four steps, matching v1's breakpoints where they exist.
   Every step must reset the span modifiers, or a `span 3` in a 2-track grid
   silently creates implicit columns and pushes the page under the rail.
   ============================================================================= */

/* 1440px — 4 tracks would fall under ~40ch of prose. Drop to 3. */
@media (max-width:1440px){
  .mosaic{grid-template-columns:repeat(3,minmax(0,1fr))}
  .t--w3,.t.w3{grid-column:span 3}                 /* = full width, still valid */
  .t--text.t--w3{columns:2}
}

/* 1120px — 3 tracks would fall under ~40ch. Drop to 2, and --w3 becomes --w2. */
@media (max-width:1120px){
  .mosaic{grid-template-columns:repeat(2,minmax(0,1fr))}
  .t--w2,.t.w2,.t--w3,.t.w3{grid-column:span 2}
  .t--text.t--w2,.t--text.t--w3{columns:2}
  .cols--3{column-count:2}
}

/* 1100px — align with v1: multi-column prose is over. One column of running
   text is correct below here; only tiles stay side by side. */
@media (max-width:1100px){
  .cols,.cols--3{column-count:1;max-width:var(--measure)}
  .cols p{orphans:2;widows:2}
}

/* 700px — one tile per row. Every span collapses to 1, --h2 to 1 row. */
@media (max-width:700px){
  .mosaic{grid-template-columns:minmax(0,1fr);row-gap:1.25rem}
  .t--w2,.t.w2,.t--w3,.t.w3{grid-column:auto}
  .t--h2,.t.h2{grid-row:auto}
  .t--h2 > .frame{aspect-ratio:4/3;min-height:0}
  .t--text.t--w2,.t--text.t--w3{columns:1}
  .steps{grid-template-columns:minmax(0,1fr)}
  .abstract__l{grid-template-columns:minmax(0,1fr)}
  .keys,.check{grid-template-columns:minmax(0,1fr)}
}

/* 420px — match v1's tight end: smaller fact numbers, tighter step indent. */
@media (max-width:420px){
  .abstract{padding:.7rem .75rem .8rem}
  .t--fact > b{font-size:1.3rem}
  .step{padding-left:2.5rem}
  .step::before{left:.7rem}
  .subhead{gap:.6rem;font-size:.68rem}
  .note{padding:.45rem .6rem}
}

/* Reduced motion — nothing here animates; the hover colour shift on an
   .abstract link is a paint change, not motion, so it stays. */

/* Print — no grids, no fills that waste ink, no multicol. */
@media print{
  .mosaic,.steps,.keys,.check,.abstract__l{display:block}
  .cols,.cols--3{column-count:1}
  .t,.step{break-inside:avoid;margin-bottom:.6rem}
  .t--code,.step,.abstract{background:none}
  .note{background:none;border-left-width:2px}
  .abstract__l a{text-decoration:none}
}
