/* grid.css — The grille itself — chord grid, book layout, chord symbols. Shared with
   the chords verifier's Done preview, so that the reviewer signs off on
   the lattice this app draws and never a look-alike copy. Keep it free
   of app chrome: the preview loads only this and tokens.css.

   Cut from the single style.css on 2026-08-02. The <link> order in
   index.html IS the cascade order these were split at; reordering the
   tags changes which rule wins. */

/* ---------------------------------------------------------- chord grid */

/* All grid dimensions are em-based so the JS fit pass can scale the whole grid
   to the viewport height by adjusting this one font-size. The font grows with
   the panel width (2.6cqw) up to a 15px ceiling, so the chords stay a readable
   lead-sheet size instead of ballooning on a wide screen — a sparse tune (one
   chord per bar, e.g. Annie Laurie) needs no more than a busy one (Ask Me Now)
   to read, and a smaller grid also fits the page better. The grid fills its
   panel until the ceiling is hit, then stops widening: 38.5em is the width at
   which 2.6cqw reaches the ceiling (1 / 0.026 ≈ 38.5em, independent of the px
   value), so below the ceiling max-width never binds (the grid fills the panel)
   and at/above it the grid caps there (~15px × 38.5em ≈ 577px), centered.
   Chords never shrink to fit their slots, so fitGridWidth shrinks the font only
   if a busy bar would still collide at the available width. */
.grid {
  max-width: 38.5em;
  margin: 0 auto;
  padding-left: 1.4em;
  /* Container-relative (the .panel is an inline-size container): the grid
     shrinks when the chord panel shares the row with the melody panel. */
  font-size: clamp(10px, 2.6cqw, 15px);
}

/* Form badge on the first section's label row — section letter left, form
   badge right — mirroring the book layout's .bx-form. Sits inside .grid so it
   scales with the fitted grid font. */
.sec-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
}
/* Equal bottom margins so the two badges' borders sit on the same line and the
   row keeps the section label's usual 0.3em gap to the grid below. */
.sec-head .grid-form { margin-bottom: 0.3em; }
.grid-form {
  border: 0.1em solid var(--line);
  font-family: var(--font-cond);
  font-size: 1.1em;
  line-height: 1;
  letter-spacing: 0.1em;
  padding: 0.12em 0.5em;
  margin-bottom: 0.4em;
  text-transform: uppercase;
}

.section { margin-bottom: 0.0em; }

.sec-label {
  display: inline-block;
  background: var(--fg);
  color: var(--bg);
  font-family: var(--font-cond);
  font-weight: 400;
  font-size: 1.0em;
  line-height: 1;
  padding: 0.1em 0.2em;
  margin-bottom: 0.3em;
  margin-left: -1.0em; /* nudge the badge left, closer to the barline gutter */
}

/* Grid label row: strain name ("Impro") and section letter ("A") as two
   separate texts — the strain reads as lighter context, the letter as the
   filled badge. Plain chorus letters render the badge alone (no .sec-labels). */
.sec-labels {
  display: flex;
  align-items: baseline;
  gap: 0.35em;
  margin-left: -1.0em; /* match the lone badge's gutter nudge */
}
.sec-labels .sec-label { margin-left: 0; }
.sec-strain {
  font-family: var(--font-cond);
  font-weight: 700;
  font-size: 1.0em;
  line-height: 1;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  opacity: 0.7;
}

.row {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  position: relative;
  margin-bottom: 0.7em;
}

.timesig {
  position: absolute;
  left: -0.6em;
  top: 50%;
  transform: translateY(-50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  font-family: var(--font-cond);
  font-weight: 500;
  font-size: 1.4em;
  line-height: 1;
  gap: 0.08em;
}

.bar {
  min-width: 0;
  position: relative; /* anchors the barline pseudo-elements */
  /* Just tall enough to enclose a chord box (2.1em) with a little air above and
     below; the barlines hug the row instead of towering over it. */
  min-height: 2.5em;
  /* Fixed grid of `beats` equal columns (grid-template-columns set per bar in
     fillBar). Each chord is anchored to its beat's column line, so beats sit at
     the same fraction of every bar and align vertically bar-to-bar. */
  display: grid;
  align-items: center;
  /* Uniform insets — the left inset just clears a section double-bar. Crucially
     the padding (hence the content box and its beat grid) is identical on every
     bar, which is what keeps beats aligned: the barlines are drawn as
     pseudo-elements below, NOT as borders, so a thick section bar never changes
     a bar's width. */
  padding: 0.15em 0.15em 0.15em 0.27em;
}

/* Barlines as em-scaled pseudo-elements (position:absolute → no layout effect).
   Left line on every bar; right line on the last bar of a row; section
   boundaries thicken to a double bar. */
.bar::before {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  width: 0.09em;
  background: var(--line);
}
.bar.rowlast::after,
.bar.sec-end::after {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  right: 0;
  width: 0.09em;
  background: var(--line);
}
/* Double bar (two thin lines with a small gap) at a section start/end. */
.bar.sec-start::before,
.bar.sec-end::after {
  width: 0.24em;
  background: linear-gradient(90deg,
    var(--line) 0 0.09em, transparent 0.09em 0.15em, var(--line) 0.15em 0.24em);
}
.bar.empty::before,
.bar.empty::after { content: none; }

/* Coda jump-off sign (spec §13 coda_jump): a small, subtle glyph at the start
   of the anchored bar, tucked just outside it in the inter-row gap — below the
   bar (.coda-below) when it sits in its section's last row, above (.coda-above)
   otherwise, as space allows. Shared by the grid (.bar) and book (.bx) layouts;
   both cells are already position:relative. `--muted` carries the subtle tone
   across light and dark themes. Display-only, no interaction. */
.coda-sign {
  position: absolute;
  font-size: 1em; /* the em basis the drawn sign scales with */
  color: var(--muted);
  opacity: 0.75;
  pointer-events: none;
}
/* Jump-off mark: at the start of the bar, just outside it vertically. */
.coda-sign.coda-below,
.coda-sign.coda-above { left: 0.1em; }
.coda-sign.coda-below { top: calc(100% + 0.05em); }
.coda-sign.coda-above { bottom: calc(100% + 0.05em); }
/* Landing mark: just before (left of) the first coda bar, vertically centred. */
.coda-sign.coda-before {
  right: calc(100% + 0.1em);
  top: 50%;
  transform: translateY(-50%);
}
/* Drawn coda sign: circle + two crossing lines, colour via currentColor. */
.coda-sign .coda-glyph {
  display: block;
  width: 1.5em;
  height: 1.5em;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
}

.slot {
  min-width: 0;
  overflow: visible;
  /* Left-aligned at its beat column line; content width, never compressed — a
     crowded chord overflows to the right (fitGridWidth keeps it from colliding
     with the next beat's chord). */
  justify-self: start;
  align-self: center;
}

/* Crowded bars (3+ chords, tagged .tight in fillBar) render their chords in a
   much narrower face and pack the columns tighter, so a single busy bar can't
   force the whole grid's font down — the rest of the grid stays large while the
   dense bar simply gets condensed (see fitGridWidth). The same treatment
   squeezes multi-chord boxes of the book-layout view (.bx.tight). */
.bar.tight .chord,
.bx.tight .chord {
  font-family: var(--font-cond);
  letter-spacing: -0.03em;
}
/* Narrow the middle/right columns (never the root, so the ground line and the
   root's height stay consistent with the roomy bars) and pull the columns in
   tight, so a dense bar's chords are horizontally compact but still full-height. */
.bar.tight .chord .qual,
.bx.tight .chord .qual { font-size: 1.3em; margin-left: 0.01em; }
.bar.tight .chord .acc,
.bx.tight .chord .acc { margin-left: 0.01em; }
.bar.tight .chord .alt-up,
.bar.tight .chord .alt-down,
.bx.tight .chord .alt-up,
.bx.tight .chord .alt-down { font-size: 1.2em; margin-left: 0em; letter-spacing: -0.04em; }

/* ------------------------------------------- book layout ("boxes") view */

/* Re-creation of the printed grille: one contiguous lattice, (up to) 8 boxes
   per row, one section per row, the section letter in the left margin. All
   dimensions are em-based so fitBoxes can zoom the whole lattice through this
   one font-size; individual chords get a per-chord squeeze when they'd
   overflow their box (or their half/slot of it). */
.boxgrid {
  max-width: 58em;
  margin: 0 auto;
  padding-left: 1.6em; /* gutter for the section letters */
  font-size: clamp(9px, 2.6cqw, 16px);
}

/* Strain head above each lattice: caption ("Impro") on the left, that
   strain's form label ("16 A B") right — one per strain. */
.bx-blockhead {
  display: flex;
  align-items: baseline;
  margin-top: 1.2em;
}
.boxgrid > .bx-blockhead:first-child { margin-top: 0; }
.bx-blockhead .bx-caption { margin-top: 0; }
.bx-blockhead .bx-form { margin-left: auto; }

.bx-form {
  border: 0.1em solid var(--line);
  font-family: var(--font-cond);
  font-size: 1.1em;
  line-height: 1;
  letter-spacing: 0.1em;
  padding: 0.12em 0.5em;
  margin-bottom: 0.4em;
  text-transform: uppercase;
}

/* Auxiliary blocks (verse/intro/coda) print as their own grille. */
.bx-block + .bx-block,
.bx-caption { margin-top: 1.2em; }

/* Book-layout variants: captioned box rows below the lattice, clickable to
   swap into it — same states/behavior as the grid view's .variant blocks. */
.bx-variants-title { margin-top: 1.4em; }
.bx-variant {
  margin: 0.5em 0 0.9em;
  border: 1px solid transparent;
  border-radius: 0.5em;
  padding: 0.4em 0.5em;
}
.bx-variant .variant-caption { margin: 0 0 0.35em; }
.bx-variant .bx-block { margin-top: 0; }
.bx-variant.clickable { cursor: pointer; transition: background 0.12s, border-color 0.12s; }
.bx-variant.clickable:hover { background: var(--panel); border-color: var(--border); }
.bx-variant.clickable:focus-visible { outline: 2px solid var(--muted); outline-offset: 2px; }
.bx-variant.clickable.active { border-color: var(--accent); background: var(--chip-bg); }
.bx-variant.clickable.active .variant-caption::after {
  content: " ✓ applied";
  color: var(--accent-ink);
  font-weight: 600;
}

.bx-caption {
  /* Match the chord grid's .sec-strain so the strain name reads the same in
     both views (size, spacing and lighter weight). */
  font-family: var(--font-cond);
  font-weight: 700;
  font-size: 1.0em;
  line-height: 1;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  opacity: 0.7;
  margin-bottom: 0.0em;
}

/* Two four-bar phrases per row: bars within a group of 4 touch (shared single
   borders via .merge-left), the narrow middle track parts the groups. */
.bx-row {
  display: grid;
  grid-template-columns: repeat(4, 1fr) 0.18em repeat(4, 1fr);
  position: relative; /* anchors the section letter in the gutter */
}

/* Air between the rows. */
.bx-row + .bx-row { margin-top: 0.55em; }

/* Section letter in the left margin, centred on its section's first row. */
.bx-seclabel {
  position: absolute;
  left: -1.6em;
  top: 50%;
  transform: translateY(-50%);
  background: var(--fg);
  color: var(--bg);
  font-family: var(--font-cond);
  font-size: 1.0em;
  line-height: 1;
  padding: 0.12em 0.22em;
}

/* Section shading, shared by BOTH chord views: boxes (book layout) and bars
   (4-bar grid) mix their section's hue (--bxhue, set by the renderer) into
   the theme background — a light wash in light mode, a stronger mix in dark
   mode where 12% wouldn't show. The topbar droplet toggles body.tint-off. */
.bx,
.section .bar:not(.empty) {
  --bxtint: color-mix(in srgb, var(--bxhue, transparent) 12%, var(--bg));
  background-color: var(--bxtint);
}

:root[data-theme="dark"] .bx,
:root[data-theme="dark"] .section .bar:not(.empty) {
  --bxtint: color-mix(in srgb, var(--bxhue, transparent) 26%, var(--bg));
}

body.tint-off .bx,
body.tint-off .section .bar:not(.empty) { --bxtint: var(--bg); }

.bx {
  position: relative;
  min-height: 5em;
  min-width: 0;
  border: 0.2em solid var(--line);
}

.bx.merge-left { border-left: none; }

/* Lone chord: big, centred — like the printed box. */
.bx-solo {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  padding: 0.1em 0.3em;
}

/* Solo chords fill their room; the main chord of an inset pair stays a bit
   smaller so its ink clears the inset quadrant. fitBoxes squeezes overflows. */
.bx-solo .chord { font-size: 1.15em; }
.bx-main .chord { font-size: 1.05em; }

/* Two chords: the book's diagonal split — the line runs from the top-right
   corner to the bottom-left one, making the top-left triangle the home of the
   first chord and the bottom-right triangle that of the second. (The gradient
   axis points to the bottom-right corner; the drawn stripe lies perpendicular
   to it, i.e. along the top-right ↔ bottom-left diagonal.) */
.bx.duo {
  background-image: linear-gradient(to bottom right,
    transparent calc(50% - 0.03em),
    var(--line) calc(50% - 0.03em),
    var(--line) calc(50% + 0.03em),
    transparent calc(50% + 0.03em));
}

/* Each chord sits by the centre of gravity of its triangle — the centroid is a
   third in from the right-angle corner (33%) — backed off a little further
   from the diagonal (to 27% resp. 73%) so the symbols keep clear air to the
   line. */
.bx-a,
.bx-b {
  position: absolute;
  font-size: 1.05em;
  white-space: nowrap;
  transform: translate(-50%, -50%);
}

/* The first chord sits a touch lower than its mirror: a root accidental (♭/♯)
   adds ink above the chord, which touched the box's top border at 27%. */
.bx-a { top: 31%; left: 27%; }
.bx-b { top: 73%; left: 73%; }

/* Uneven two-chord bars (1+4, 1+2, …): the long chord big, the short one in
   a small framed box in the corner matching its position in the bar. The main
   chord sits on the same anchor as the diagonal split's chords (.bx-a/.bx-b),
   so a beat-1 chord lands in the same spot whether its partner falls on beat
   3 or 4 (Autumn in New York bars 27/28); the anchor also keeps it clear of
   the opaque inset quadrant. */
.bx-main {
  position: absolute;
  white-space: nowrap;
  transform: translate(-50%, -50%);
}

/* The smaller main font keeps a root accidental's ink
   clear of the inset's edge. */
.bx-main.clear-bottom { top: 31%; left: 27%; }
.bx-main.clear-top { top: 73%; left: 73%; }

/* The inset is one quadrant of the box (half width × half height); its frame
   is an inside line, much thinner than the frame (0.075em at the 0.8em font =
   0.06em at the box scale). */
.bx-inset {
  position: absolute;
  width: 50%;
  height: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 0.075em solid var(--line);
  /* The box's own opaque tint (masks the main chord underneath); follows the
     .tint-off override through --bxtint. */
  background-color: var(--bxtint, var(--bg));
  font-size: 0.8em;
  line-height: 1;
  white-space: nowrap;
}

.bx-inset .bx-beat { align-self: flex-start; padding-top: 0.2em; }

.bx-inset.inset-late { right: 0; bottom: 0; border-right: none; border-bottom: none; }
.bx-inset.inset-early { left: 0; top: 0; border-left: none; border-top: none; }

/* Three or more chords: the box halves horizontally (top = the bar's first
   half, bottom = the second); a half with several chords splits into
   side-by-side cells — four chords make the 2×2 quadrants. */
.bx-halves {
  display: flex;
  flex-direction: column;
  height: 100%;
}

.bx-half {
  flex: 1;
  min-height: 0;
  display: flex;
  font-size: 0.8em;
}

/* Inside lines, much thinner than the box frame: 0.075em at the halves'
   0.8em font = 0.06em at the box scale. */
.bx-half + .bx-half { border-top: 0.075em solid var(--line); }

.bx-cell {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0 0.15em;
  white-space: nowrap;
}

.bx-cell + .bx-cell { border-left: 0.075em solid var(--line); }

/* Small beat digit before an off-default chord (the book's superscripts). */
.bx-beat {
  font-family: var(--font-cond);
  font-size: 0.9em;
  line-height: 1;
  margin-right: 0.1em;
  vertical-align: 1.1em;
}

/* In the flex containers the sup is a flex item: lift it to the top edge. */
.bx-solo .bx-beat { align-self: flex-start; padding-top: 0.35em; }

/* -------------------------------------------------------- chord symbols */

/* The chord is a flex row: an optional "(", the box grid, an optional bass note,
   an optional ")". */
.chord {
  display: inline-flex;
  align-items: center;
  font-family: var(--font-cond);
  font-weight: 400;
  line-height: 1;
  white-space: nowrap;
}

/* Fixed box grid (Figure D.3): a full-height root letter on the left, then a
   middle column (accidental over core quality) and a right column (alt-up over
   alt-down). The two rows are a fixed height in em, so the root always spans the
   same box and every chord shares one ground line — B7♯11 and B♭7♯11 line up
   whether or not there's an accidental. Anything overspilling a box (an enlarged
   flat, a tall alteration) overflows visibly without nudging the layout. */
.chord .box {
  display: inline-grid;
  grid-template-columns: auto auto auto; /* root | middle | alts */
  grid-template-rows: 1.05em 1.05em;
  align-items: center;
}

.chord .root {
  grid-column: 1;
  grid-row: 1 / 3;
  align-self: center;
  font-size: 2.1em;
  line-height: 0.72;
  font-weight: 400;
}

/* Middle column, top box: root accidental as a superscript. ♭ and ♯ come from
   the bundled music subset (Grille Chord Glyphs) at matched optical sizes and
   registration, so one rule serves both — the old per-glyph enlargements
   compensated for device fallback fonts where ♭ ran small. */
.chord .acc {
  grid-column: 2;
  grid-row: 1;
  align-self: start;
  justify-self: start;
  margin-left: 0.06em;
  font-size: 1.2em;
  line-height: .24;
  position: relative;
  top: 0.35em;
}

/* Flats inside qualities/alterations/numerals keep their span as a tuning
   hook, but need no enlargement with the bundled glyphs. */
.chord .fl { font-size: 1em; }

/* The half-diminished ø (Bravura's circle-with-slash) is drawn taller than
   Saira's digits — scale it down to sit like a letterform next to the 7. */
.chord .hd { font-size: 0.82em; }

/* Middle column, bottom box: the core quality (7, -7, Δ7, ø7 …). */
.chord .qual {
  grid-column: 2;
  grid-row: 2;
  align-self: center;
  justify-self: start;
  margin-left: 0.06em;
  margin-right: 0.06em;
  font-size: 1.2em;
  line-height: 0.85;
}

/* Right column: up to two alterations. A lone one sits in the upper box
   (superscript); a pair straddles the core quality (Figure D.3). Extended
   chords like B♭7♯9♯5 or A♭7(13) stay about a letter-width wide. */
.chord .alt-up,
.chord .alt-down {
  grid-column: 3;
  justify-self: start;
  margin-left: 0.2em;
  font-size: 1.1em;
  line-height: 0.95;
}

.chord .alt-up { grid-row: 1; align-self: end; }

/* Inside stacked alterations (♯11, ♭5, ♯9 …) the accidental sits a touch
   smaller and lower than its digits, like the book's engraving. */
.chord .alt-up .fl, .chord .alt-down .fl,
.chord .alt-up .sh, .chord .alt-down .sh {
  font-size: 0.85em;
  position: relative;
  top: 0.05em;
  margin-right: 0.08em;
}
.chord .alt-down { grid-row: 2; align-self: start; }

/* Bass note sits below-right of the box, after a short slash (Aø7/E♭). */
.chord .bass {
  align-self: flex-end;
  transform: translateY(0.3em);
  margin-left: 0.08em;
  font-size: 1.2em;
  line-height: 1;
}

/* Enlarge the slash separator only — the bass note/degree keeps the .bass size. */
.chord .bass .slash {
  font-size: 1.5em;
}

.chord .paren {
  font-size: 1.6em;
  font-weight: 400;
  opacity: 0.8;
}

.chord.optional { opacity: 0.85; }
.chord.optional .root { font-size: 1.7em; }

.chord .nc {
  font-size: 1.1em;
  font-variant: small-caps;
  color: var(--muted);
}

.chord-raw {
  font-family: Consolas, monospace;
  font-size: 1em;
  color: #c96e6e;
}

