@charset "utf-8";
/* ═══════════════════════════════════════════════════════════════════════════
   ART IN PROPORTION — project theme (v2.31)
   "The proportion atelier." A graphite studio wall at dusk with real sheets of
   drawing paper laid on it; the wall itself is a field of rays fanning out of
   the bottom-left corner — the same corner the canvas puts vertex A in, so the
   backdrop IS a dilation from the center every triangle grows from.

   Four studio pigments, and each one MEANS something in the app:
       sanguine (red chalk) = the original triangle you invented
       ochre                = scale factor / the measurement you chose
       verdigris            = verified, correct, finished
       graphite             = the ruled sheet and its construction lines
   Part I / II / III wear those colors in order, so the palette doubles as a
   legend — and the three nav glyphs are the SAME scalene triangle at three
   sizes, which is the project in one mark.

   Type: Bodoni Moda for display. A Didone is defined by the RATIO of its thick
   strokes to its thin ones, so the headline face is itself a proportion study.
   Archivo carries the UI, IBM Plex Mono carries every measurement.

   Shared by ArtInProportion.html (student) and ArtInProportionShowAll.html
   (teacher, which ShowProjects.html loads in a height-fitted iframe — so
   nothing here may use 100vh sizing). Loads AFTER bootstrap.min.css, so ties
   go to this file; a few Bootstrap classes that AIP.js writes at runtime
   (.text-success, .text-danger, .disabled, .active) are re-skinned below.
   ═══════════════════════════════════════════════════════════════════════════ */

:root {
    --wall: #21242b;              /* studio wall */
    --wall-2: #292d36;            /* raised panel / tool rail */
    --wall-3: #3a404c;            /* control borders */
    --sheet: #f7f3ec;             /* drawing paper */
    --sheet-2: #ece4d6;           /* toned paper — table head, master row */
    --sheet-edge: #d8cdb9;
    --ink: #23262d;               /* text on paper */
    --ink-2: #5b6270;
    --faint: #9aa0ad;
    --chalk: #ece8e0;             /* text on the wall */
    --chalk-2: #a7adba;

    --sanguine: #c0563c;          /* red chalk — the original triangle */
    --sanguine-lt: #e08a70;
    --sanguine-dk: #96412c;
    --ochre: #d9a441;             /* scale factor */
    --ochre-dk: #9c7220;
    --verdigris: #56a08a;         /* verified */
    --verdigris-dk: #2f7a63;
    --graphite: #5a6270;          /* ruled lines */
    --azure: #3b6ea5;             /* the artwork itself — Part 4 wood pieces */

    --disp: "Bodoni Moda", Georgia, "Times New Roman", serif;
    --ui: "Archivo", "Segoe UI", system-ui, sans-serif;
    --mono: "IBM Plex Mono", ui-monospace, Consolas, monospace;
}

* { box-sizing: border-box; }
/* Must outrank #Part2{display:grid} below — an id beats [hidden] on its own. */
[hidden] { display: none !important; }

/* ── The wall ──────────────────────────────────────────────────────────────
   Two fixed backdrop layers under a transparent body (the wall color
   propagates to the root canvas, so negative z-index still paints).        */
html { scrollbar-color: #3a404c #21242b; }
body {
    margin: 0;
    background: var(--wall);
    color: var(--chalk);
    font-family: var(--ui);
    font-size: 16px;
    line-height: 1.55;
}
/* Rays out of the bottom-left corner: the dilation field. Masked so they fade
   with distance from the center instead of tiling the whole page. */
body::before {
    content: ""; position: fixed; inset: 0; z-index: -2; pointer-events: none;
    background: repeating-conic-gradient(from -1deg at 4% 97%,
        rgba(236, 232, 224, .075) 0deg .16deg, transparent .16deg 4.5deg);
    -webkit-mask-image: radial-gradient(115% 115% at 4% 97%, #000 5%, transparent 68%);
    mask-image: radial-gradient(115% 115% at 4% 97%, #000 5%, transparent 68%);
}
body::after {
    content: ""; position: fixed; inset: -10%; z-index: -3; pointer-events: none;
    background:
        radial-gradient(950px 640px at 5% 100%, rgba(192, 86, 60, .16), transparent 62%),
        radial-gradient(860px 540px at 97% 2%, rgba(217, 164, 65, .10), transparent 62%),
        radial-gradient(760px 760px at 62% 58%, rgba(86, 160, 138, .055), transparent 66%);
    animation: aip-breathe 34s ease-in-out infinite alternate;
}
@keyframes aip-breathe { to { transform: translate3d(-1.4%, -1%, 0) scale(1.04); } }

::selection { background: var(--sanguine); color: #fff; }
::-webkit-scrollbar { width: 11px; height: 11px; }
::-webkit-scrollbar-track { background: #21242b; }
::-webkit-scrollbar-thumb { background: #3a404c; border-radius: 8px; border: 2px solid #21242b; }
::-webkit-scrollbar-thumb:hover { background: #4b5464; }

a { color: var(--ochre); text-decoration: none; }
a:hover { color: #ecc069; }
:where(a, button, input, [contenteditable]):focus-visible {
    outline: 2px solid var(--ochre); outline-offset: 2px;
}

/* ══ TOPBAR ═══════════════════════════════════════════════════════════════ */
.aip-bar {
    position: sticky; top: 0; z-index: 500;
    display: flex; align-items: center; gap: 18px; flex-wrap: wrap;
    padding: 7px 20px;
    background: rgba(28, 31, 37, .90);
    -webkit-backdrop-filter: blur(10px); backdrop-filter: blur(10px);
    border-bottom: 1px solid #363c47;
    box-shadow: 0 1px 0 rgba(236, 232, 224, .05), 0 10px 30px rgba(0, 0, 0, .35);
}
.aip-owl { flex: 0 0 auto; display: flex; }
.aip-owl img { width: 58px; height: auto; display: block; }

.aip-wordmark {
    display: grid; grid-template-columns: auto auto auto;
    align-items: center; column-gap: 11px;
}
/* The mark: four nested scalene triangles sharing one vertex, striking
   themselves in from smallest to largest. It draws what the student draws. */
.aip-mark { grid-row: 1 / span 2; width: 44px; height: 40px; overflow: visible; }
.aip-mark .am-t {
    fill: none; stroke-width: 1.7; stroke-linejoin: round;
    stroke-dasharray: 118; stroke-dashoffset: 118;
    animation: am-draw 8.5s cubic-bezier(.5, .05, .3, 1) infinite;
}
.aip-mark .am-1 { stroke: var(--sanguine-lt); }
.aip-mark .am-2 { stroke: var(--ochre); animation-delay: .45s; }
.aip-mark .am-3 { stroke: var(--verdigris); animation-delay: .9s; }
.aip-mark .am-4 { stroke: var(--chalk); animation-delay: 1.35s; }
.aip-mark .am-v { fill: var(--sanguine-lt); animation: am-pulse 8.5s ease-in-out infinite; }
@keyframes am-draw {
    0% { stroke-dashoffset: 118; opacity: .25; }
    14% { stroke-dashoffset: 0; opacity: 1; }
    80% { stroke-dashoffset: 0; opacity: 1; }
    94%, 100% { stroke-dashoffset: 118; opacity: .25; }
}
@keyframes am-pulse { 0%, 100% { r: 2.1; opacity: .85; } 8% { r: 3.4; opacity: 1; } }

.aip-name {
    font-family: var(--disp); font-weight: 700; font-size: 25px; line-height: 1.05;
    letter-spacing: .015em; color: #fbf8f3; white-space: nowrap;
}
.aip-name i { font-style: italic; font-weight: 400; color: var(--sanguine-lt); }
.aip-ver {
    font: 500 10px/1 var(--mono); letter-spacing: .08em; color: #12141a;
    background: var(--ochre); border-radius: 3px; padding: 4px 6px;
    box-shadow: 0 2px 8px rgba(0, 0, 0, .45);
}
.aip-sub {
    grid-column: 2 / -1;
    font: 500 9px/1.5 var(--mono); letter-spacing: .3em; text-transform: uppercase;
    color: var(--chalk-2); white-space: nowrap; margin-top: 2px;
}

.aip-steps { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; margin-left: auto; }
.aip-acts { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.aip-rule { width: 1px; height: 24px; background: #3f4653; margin: 0 6px; }

/* Part chips. The glyph is deliberately SCALENE (Part 1 forbids isosceles)
   and appears at three sizes off one shape — the chips are a dilation. */
.aip-step {
    display: inline-flex; align-items: flex-end; gap: 8px;
    padding: 8px 14px; border: 1px solid #3f4653; border-radius: 2px;
    color: #c3c9d5;
    font: 600 11.5px/1 var(--ui); letter-spacing: .13em; text-transform: uppercase;
    transition: color .18s ease, border-color .18s ease, background-color .18s ease,
        box-shadow .25s ease, transform .15s ease;
}
.aip-step b {
    display: block; background: var(--pacc, var(--sanguine));
    clip-path: polygon(0 100%, 100% 100%, 63% 0);
    transition: transform .2s ease;
}
.aip-step.s1 { --pacc: var(--sanguine); }
.aip-step.s2 { --pacc: var(--ochre); }
.aip-step.s3 { --pacc: var(--verdigris); }
.aip-step.s4 { --pacc: var(--azure); }
.aip-step.s1 b { width: 9px; height: 8px; }
.aip-step.s2 b { width: 13px; height: 11px; }
.aip-step.s3 b { width: 17px; height: 15px; }
.aip-step.s4 b { width: 21px; height: 19px; }
.aip-step:hover {
    color: #fff; border-color: var(--pacc); transform: translateY(-1px);
    box-shadow: 0 0 15px color-mix(in srgb, var(--pacc) 30%, transparent);
}
.aip-step:hover b { transform: scale(1.12); transform-origin: 0 100%; }
/* AIP.js toggles .active on #P1Button/#P2Button/#P3Button */
.aip-step.active {
    color: #fff; border-color: var(--pacc);
    background: color-mix(in srgb, var(--pacc) 15%, transparent);
}

.aip-act, .aip-login {
    padding: 9px 13px; border-radius: 2px;
    font: 600 10.5px/1 var(--ui); letter-spacing: .15em; text-transform: uppercase;
    transition: color .18s ease, border-color .18s ease, box-shadow .25s ease;
}
.aip-act { border: 1px solid #3f4653; color: #c3c9d5; }
.aip-act:hover { color: var(--ochre); border-color: var(--ochre); box-shadow: 0 0 13px rgba(217, 164, 65, .22); }
/* PRINT and SVG ship disabled and AIP.js drops the class when Part 3 is done.
   Bootstrap only kills pointer events on .nav-link.disabled, so do it here. */
.aip-act.disabled { opacity: .35; pointer-events: none; }
/* LOGIN is a dashed invitation until AJAXLoad() swaps in the student's name —
   then the same anchor becomes the user menu (see the user-menu script). */
.aip-login { border: 1px dashed var(--verdigris); }
.aip-user { position: relative; }
.aip-usermenu {
    background: var(--wall-2); border: 1px solid var(--wall-3); border-radius: 2px;
    box-shadow: 0 16px 34px rgba(0, 0, 0, .5);
    padding: 4px; min-width: 140px; margin-top: 7px;
}
.aip-usermenu .dropdown-item {
    color: var(--chalk); border-radius: 2px; padding: 9px 12px;
    font: 600 10.5px/1 var(--ui); letter-spacing: .15em; text-transform: uppercase;
}
.aip-usermenu .dropdown-item:hover, .aip-usermenu .dropdown-item:focus {
    background: var(--sanguine); color: #fff8f4;
}
.aip-login.text-success { color: var(--verdigris) !important; }
.aip-login:hover { color: #7cc0aa !important; border-color: #7cc0aa; }

/* ══ PAGE SCAFFOLD ════════════════════════════════════════════════════════ */
/* #ModalContainer is a Bootstrap .container wrapping two more .containers —
   flatten it so the parts below own their own width. */
#ModalContainer { max-width: none; width: auto; padding: 0; margin: 0; }
#Part1, #Part2, #Part3, #Part4 {
    max-width: 1280px; margin: 0 auto; padding: 4px 24px 40px;
    animation: aip-reveal .4s ease both;
}
@keyframes aip-reveal { from { opacity: 0; transform: translateY(8px); } }
#Part1 { --pacc: var(--sanguine); }
#Part2 { --pacc: var(--ochre); }
#Part3 { --pacc: var(--verdigris); font-size: 1rem; font-weight: 400; }
#Part4 { --pacc: var(--azure); }

/* Gallery plaque: Didone title, the part's own triangle glyph, and the paired
   hairlines an engraved plate would carry. The glyph scales in from its
   bottom-left vertex — the entrance is itself a dilation. */
#Part1 h1, #Part2 h1, #Part3 h1, #Part4 h1 {
    position: relative;
    display: flex; align-items: flex-end; gap: 16px;
    margin: 30px 0 22px; padding-bottom: 15px;
    font-family: var(--disp); font-weight: 700; font-size: clamp(28px, 3.4vw, 42px);
    line-height: 1.05; letter-spacing: .005em; color: #fbf8f3;
}
#Part1 h1::before, #Part2 h1::before, #Part3 h1::before, #Part4 h1::before {
    content: ""; flex: 0 0 auto; width: 26px; height: 23px;
    background: var(--pacc);
    clip-path: polygon(0 100%, 100% 100%, 63% 0);
    animation: aip-dilate .55s cubic-bezier(.2, .8, .3, 1.15) both;
}
#Part1 h1::after, #Part2 h1::after, #Part3 h1::after, #Part4 h1::after {
    content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 4px;
    border-top: 2px solid var(--pacc);
    border-bottom: 1px solid rgba(236, 232, 224, .22);
}
@keyframes aip-dilate {
    from { opacity: 0; transform: scale(.25); transform-origin: 0 100%; }
    to { opacity: 1; transform: scale(1); transform-origin: 0 100%; }
}

/* A sheet of drawing paper laid on the wall. */
.aip-sheet {
    background: var(--sheet); color: var(--ink);
    border: 1px solid var(--sheet-edge); border-radius: 2px;
    box-shadow: 0 18px 40px rgba(0, 0, 0, .40), 0 2px 0 rgba(255, 255, 255, .05);
}

/* ══ PART 1 — the brief ═══════════════════════════════════════════════════ */
#Instructions0 {
    max-width: 720px; padding: 26px 30px 28px;
    font-size: 1rem; /* neutralize Bootstrap .fs-4 */
    background: var(--sheet); color: var(--ink);
    border: 1px solid var(--sheet-edge); border-top: 3px solid var(--sanguine);
    box-shadow: 0 18px 40px rgba(0, 0, 0, .40);
}
#Instructions0 h1 { color: var(--ink); margin-top: 0; }
#Instructions0 h1::after { border-bottom-color: rgba(35, 38, 45, .18); }
#Instructions0 li {
    list-style: none;
    display: grid; grid-template-columns: 20px 1fr; align-items: start; gap: 11px;
    margin: 0 0 0 0 !important; padding: 8px 4px;
    font-size: .96rem; color: var(--ink-2);
    border-bottom: 1px dashed rgba(90, 98, 112, .22);
}
#Instructions0 li:last-of-type { border-bottom: 0; }
#Instructions0 li::before {
    content: ""; width: 11px; height: 10px; margin-top: 6px;
    background: var(--sanguine); opacity: .8;
    clip-path: polygon(0 100%, 100% 100%, 63% 0);
}
/* the lead sentence sits as a bare text node inside #Instructions0 */
#Instructions0 br { line-height: 2.4; }

/* THE ENTRY. This is the one door into the project, so it is lit like the brief
   rather than recessed into the wall — a dark rail here read as "disabled" and
   students could not tell where to begin. The prove/build sheet does not exist
   until START is pressed, which leaves exactly one thing to do on arrival. */
#Tri0Input {
    max-width: 720px; margin: 0; padding: 22px 26px 24px;
    background: var(--sheet); color: var(--ink);
    border: 1px solid var(--sheet-edge); border-top: 3px solid var(--sanguine);
    box-shadow: 0 18px 40px rgba(0, 0, 0, .40);
    animation: aip-reveal .4s ease both;
}
.aip-starteyebrow {
    margin: 0 0 4px;
    font: 600 10px/1 var(--mono); letter-spacing: .26em; text-transform: uppercase;
    color: var(--sanguine-dk);
}
#Tri0Input .aip-provehead { margin-bottom: 16px; }
#Tri0Input p var, .aip-starthint var {
    font-family: var(--mono); font-style: normal; font-weight: 600; color: var(--sanguine-dk);
}
.aip-startrow {
    display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
    padding: 14px 16px;
    background: var(--sheet-2); border: 1px solid var(--sheet-edge); border-radius: 2px;
}
.aip-speclabel {
    font: 600 9.5px/1 var(--mono); letter-spacing: .22em; text-transform: uppercase;
    color: var(--ink-2);
}
/* Side names are lowercase BY CONVENTION — side a is opposite vertex A — so the
   label's uppercasing must not touch them. Vertices stay capital (ABC). */
.aip-speclabel var { text-transform: none; font-style: normal; letter-spacing: .1em; color: var(--ink); }
#TriangleName {
    font-family: var(--disp); font-weight: 700; font-size: 25px; line-height: 1;
    color: var(--sanguine-dk); letter-spacing: .04em;
}
#Sides {
    width: 170px; padding: 10px 12px;
    background: #fffdf7; color: var(--ink);
    border: 1px solid var(--graphite); border-radius: 2px;
    font: 500 16px/1 var(--mono); text-align: center; letter-spacing: .06em;
    caret-color: var(--sanguine);
}
#Sides::placeholder { color: #a49a86; letter-spacing: .1em; }
#Sides:focus { border-color: var(--ochre); box-shadow: 0 0 0 3px rgba(217, 164, 65, .25); outline: none; }
.aip-btn {
    margin-left: auto; padding: 11px 26px;
    background: var(--sanguine); color: #fff8f4;
    border: 1px solid var(--sanguine-dk); border-radius: 2px; cursor: pointer;
    font: 700 11.5px/1 var(--ui); letter-spacing: .2em; text-transform: uppercase;
    transition: background-color .16s ease, transform .12s ease, box-shadow .2s ease;
}
.aip-btn:hover { background: #d0654a; box-shadow: 0 6px 20px rgba(192, 86, 60, .35); transform: translateY(-1px); }
.aip-btn:active { transform: translateY(1px); }
.aip-btn:disabled {
    opacity: .35; cursor: not-allowed; pointer-events: none;
    background: var(--wall-3); border-color: var(--wall-3); box-shadow: none; transform: none;
}
/* the ochre nudge when the build completes and START wakes up */
.aip-pulse { animation: aip-pulse 1.5s ease-in-out 3; }
@keyframes aip-pulse {
    0%, 100% { box-shadow: none; }
    50% { box-shadow: 0 0 0 4px rgba(217, 164, 65, .35), 0 0 24px rgba(217, 164, 65, .5); }
}

/* ── Part 1 layout: brief + rail on the left, prove/build sheet on the right,
      mirroring Part 2's sheet-beside-ledger grid. ─────────────────────────── */
/* Left = the conditions, a reference the student keeps glancing back at, so it
   sticks. Right = the work, steps 1-2-3 straight down one column — putting the
   entry in the left column made step 2 sit ABOVE step 1 and the flow read
   backwards. Nothing is centred or re-columned on START: the sheet simply
   slots in under the entry card, so revealing it moves nothing. */
#Part1 {
    display: grid; grid-template-columns: minmax(300px, 0.88fr) minmax(420px, 1.12fr);
    grid-template-rows: max-content 1fr;
    column-gap: 30px; row-gap: 22px; align-items: start;
}
/* Sticky offset sits just under the 73px topbar and BELOW where the card
   naturally rests, so it never nudges the card down at rest — its top stays
   level with step 1 and only engages once the steps scroll past. */
#Instructions0 {
    grid-column: 1; grid-row: 1 / span 2; max-width: none;
    position: sticky; top: 74px;
}
#Part1 > #Tri0Input { grid-column: 2; grid-row: 1; margin: 0; max-width: none; }
#ProvePanel { grid-column: 2; grid-row: 2; }

/* ── The prove/build sheet ────────────────────────────────────────────────── */
#ProvePanel {
    padding: 24px 26px 22px;
    background: var(--sheet); color: var(--ink);
    border: 1px solid var(--sheet-edge); border-top: 3px solid var(--ochre);
    box-shadow: 0 18px 40px rgba(0, 0, 0, .40);
}
.aip-provehead { display: flex; gap: 14px; align-items: flex-start; margin: 0 0 16px; }
.aip-provenum {
    flex: 0 0 auto; width: 28px; height: 28px; display: grid; place-items: center;
    font: 600 15px/1 var(--mono); color: #fff8f4; background: var(--sanguine);
    clip-path: polygon(0 0, calc(100% - 8px) 0, 100% 8px, 100% 100%, 0 100%);
}
/* the three steps wear the pigments in order, same as Parts 1/2/3 */
#ProveStep .aip-provenum { background: var(--ochre-dk); }
#BuildStep .aip-provenum { background: var(--verdigris-dk); }
.aip-provehead h2 {
    margin: 0 0 4px; font-family: var(--disp); font-weight: 700; font-size: 22px;
    line-height: 1.15; color: var(--ink);
}
.aip-provehead p { margin: 0; font-size: .88rem; line-height: 1.5; color: var(--ink-2); }

/* the three inequality rows: mono math with pigment-coded blanks */
.tiq-rows { display: grid; gap: 10px; margin: 0 0 14px; }
.tiq-row {
    display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap;
    font-family: var(--mono); font-size: 19px; color: var(--ink);
    padding: 8px 10px; border-bottom: 1px dashed rgba(90, 98, 112, .25);
}
.tiq {
    width: 5.5ch; padding: 2px 4px;
    background: rgba(217, 164, 65, .07); color: var(--pv, var(--ink));
    border: 0; border-bottom: 2px solid var(--pv, var(--graphite));
    font: 500 19px/1.3 var(--mono); text-align: center; caret-color: var(--sanguine);
}
.tiq:focus { outline: 0; background: #fffdf7; box-shadow: 0 2px 0 var(--pv, var(--ochre)); }
.tiq[data-var="a"] { --pv: var(--sanguine-dk); }
.tiq[data-var="b"] { --pv: var(--ochre-dk); }
.tiq[data-var="c"] { --pv: var(--verdigris-dk); }
.tiq::placeholder { color: color-mix(in srgb, var(--pv, var(--graphite)) 55%, transparent); font-style: italic; }
.tiq.tiq-bad { background: rgba(192, 86, 60, .12); border-bottom-color: var(--sanguine); }
/* the student's own simplification: → [sum] > [side], graded with a mark */
.tiq-simpwrap { display: inline-flex; align-items: baseline; gap: 8px; margin-left: auto; }
.tiq-arrow { color: var(--faint); }
.tiq-simp { --pv: var(--graphite); background: rgba(90, 98, 112, .08); }
.tiq-mark { min-width: 1.3ch; text-align: center; font-size: 21px; font-weight: 700; line-height: 1; align-self: center; }
.tiq-mark.ok { color: var(--verdigris-dk); }
.tiq-mark.bad { color: var(--sanguine-dk); }

.tiq-foot { display: flex; align-items: center; gap: 14px; margin: 0 0 22px; }
.aip-btn--check { margin-left: 0; background: var(--verdigris-dk); border-color: #235c49; }
.aip-btn--check:hover { background: var(--verdigris); box-shadow: 0 6px 20px rgba(86, 160, 138, .35); }
#IneqMsg { margin: 0; font-size: .85rem; line-height: 1.45; color: var(--ink-2); }
#IneqMsg.ok { color: var(--verdigris-dk); font-weight: 600; }
#IneqMsg.bad { color: var(--sanguine-dk); font-weight: 600; }

/* Each step sleeps until the one before it is done: step 1 until START names
   the sides, step 2 until the inequalities are proved. */
#ProveStep.aip-locked, #BuildStep.aip-locked { opacity: .45; filter: grayscale(.35); }
#BuildStep { border-top: 1px solid rgba(90, 98, 112, .18); padding-top: 18px; }
#BuildStep.aip-locked #BuildCanvas, #BuildStep.aip-locked .build-hud { pointer-events: none; }
.aip-locknote { display: none; margin: 0 0 10px; font: 500 12px/1.4 var(--mono); color: var(--ochre-dk); }
#ProveStep.aip-locked .aip-locknote, #BuildStep.aip-locked .aip-locknote { display: block; }
.tiq:disabled, .aip-btn:disabled { cursor: not-allowed; }

/* the naming START hands down — the same letters Part 2 will use */
#NameNote {
    margin: 0 0 14px; padding: 9px 12px;
    background: rgba(217, 164, 65, .10); border-left: 3px solid var(--ochre);
    font-size: .87rem; line-height: 1.5; color: var(--ink-2);
}
#NameNote b { font-family: var(--mono); font-weight: 600; margin-right: .75em; }
#NameNote i { font-family: var(--disp); font-style: italic; font-weight: 600; }
#NameNote .nv-a { color: var(--sanguine-dk); }
#NameNote .nv-b { color: var(--ochre-dk); }
#NameNote .nv-c { color: var(--verdigris-dk); }

#BuildDone { display: block; width: 100%; margin: 14px 0 0; }

#BuildCanvas {
    display: block; width: 100%; height: 340px; touch-action: none; cursor: grab;
    border: 1px solid var(--sheet-edge); background: var(--paper, #fbf8f2);
    background-image:
        linear-gradient(rgba(90, 98, 112, .10) 1px, transparent 1px),
        linear-gradient(90deg, rgba(90, 98, 112, .10) 1px, transparent 1px);
    background-size: 20px 20px;
}
#BuildCanvas.dragging { cursor: grabbing; }
.build-hud {
    display: flex; align-items: baseline; gap: 12px; margin-top: 10px;
    font: 500 12.5px/1.5 var(--mono); color: var(--ink-2);
}
#BuildMsg { flex: 1 1 auto; }
#BuildMsg.ok { color: var(--verdigris-dk); font-weight: 600; }
#JointCount { flex: 0 0 auto; color: var(--ink); }
#BuildReset {
    flex: 0 0 auto; padding: 5px 12px; cursor: pointer;
    background: transparent; color: var(--ink-2);
    border: 1px solid rgba(90, 98, 112, .4); border-radius: 2px;
    font: 600 10px/1 var(--ui); letter-spacing: .14em; text-transform: uppercase;
    transition: color .15s ease, border-color .15s ease;
}
#BuildReset:hover { color: var(--sanguine-dk); border-color: var(--sanguine); }

/* ══ PART 2 — sheet beside ledger ═════════════════════════════════════════
   CSS-only two-column layout: the drawing stays pinned in view while the
   table is filled in. Source order is untouched — only grid placement moves. */
/* The sheet track is sized explicitly: left to `auto` it would resolve to the
   canvas bitmap's intrinsic 756px and starve the ledger column. */
#Part2 {
    display: grid; grid-template-columns: minmax(0, 1fr) clamp(340px, 46%, 620px);
    column-gap: 34px; align-items: start;
}
/* The plaque runs the full width so both paper panels start on the same line
   and end level — the ledger stretches to whatever height the sheet needs. */
#Part2 > h1 { grid-column: 1 / -1; grid-row: 1; }
#Part2 > #TriangleTable { grid-column: 1; grid-row: 2; align-self: stretch; }
#CanvasContainer {
    grid-column: 2; grid-row: 2; align-self: stretch;
    display: flex; flex-direction: column; justify-content: center;
    width: auto; max-width: none; margin: 0; padding: 18px 18px 14px;
    background: var(--sheet); border: 1px solid var(--sheet-edge);
    box-shadow: 0 20px 44px rgba(0, 0, 0, .45);
}
#TriangleCanvas {
    display: block; border: 0 !important;
    width: 100%; max-width: 756px; height: auto;
    background: transparent;
}

/* The ledger. Every measurement is mono; the head wears the pigment of the
   column it holds. */
#TriangleTable {
    width: 100%; margin: 0; border-collapse: collapse;
    background: var(--sheet); color: var(--ink);
    border: 1px solid var(--sheet-edge);
    box-shadow: 0 18px 40px rgba(0, 0, 0, .40);
    font-family: var(--mono); font-size: .84rem;
}
#TriangleTable thead td {
    padding: 12px 6px;
    background: var(--sheet-2); color: var(--ink);
    border: 0; border-bottom: 2px solid var(--graphite);
    font: 600 15px/1.3 var(--mono); letter-spacing: .08em; text-transform: uppercase;
    vertical-align: middle; white-space: nowrap;
}
#TriangleTable thead td:nth-child(1) { color: var(--sanguine-dk); }
#TriangleTable thead td:nth-child(2) { color: var(--ochre-dk); }
#TriangleTable thead td:nth-child(7) { color: var(--verdigris-dk); }
#TriangleTable thead abbr {
    text-decoration: underline dotted rgba(35, 38, 45, .35);
    text-underline-offset: 3px; cursor: help;
}
/* the § help links beside EOP and S1 */
#TriangleTable thead a {
    display: inline-grid; place-items: center; width: 20px; height: 20px;
    margin-left: 4px; border-radius: 50%;
    background: rgba(47, 122, 99, .14); color: var(--verdigris-dk) !important;
    font-size: 15px; line-height: 1; cursor: pointer;
    transition: background-color .16s ease, transform .16s ease;
}
#TriangleTable thead a:hover { background: var(--verdigris-dk); color: #f2fbf7 !important; transform: scale(1.12); }

#TriangleTable td {
    padding: 9px 6px; height: 40px;
    border: 0; border-bottom: 1px solid rgba(90, 98, 112, .16);
    text-align: center; vertical-align: middle;
    transition: background-color .3s ease, color .3s ease, box-shadow .3s ease;
}
#TriangleTable td + td { border-left: 1px solid rgba(90, 98, 112, .10); }
#TriangleTable tr:hover td { background: rgba(217, 164, 65, .07); }
/* Column 0 names the triangle — it is a row label, not a field, so it wears the
   toned paper of the head rather than the ochre tint of an editable blank. */
#TriangleTable tbody td:first-child {
    background: var(--sheet-2); color: var(--ink);
    font-weight: 600; letter-spacing: .06em; cursor: default;
}
#TriangleTable tr:hover td:first-child { background: #e5dbc9; }

/* Row 0 is the triangle the student invented — it wears sanguine, the same
   pigment the canvas draws it in. (.text-success on the <tr> is Bootstrap's;
   a declaration on the cell outranks the inherited value.) */
#TriangleTable #Tri0 td {
    background: var(--sheet-2); color: var(--sanguine-dk);
    font-weight: 600; border-bottom: 2px solid var(--graphite);
}
#TriangleTable #Tri0 td:first-child { box-shadow: inset 3px 0 0 var(--sanguine); }

/* Editable cells announce themselves: a ruled blank waiting to be filled.
   AIP.js flips contenteditable to "false" once a row checks out, so the
   "inked and locked" look arrives with no extra hook. */
#TriangleTable td[contenteditable="true"] {
    background: rgba(217, 164, 65, .06);
    box-shadow: inset 0 -1px 0 rgba(156, 114, 32, .35);
    cursor: text;
}
#TriangleTable td[contenteditable="true"]:hover { background: rgba(217, 164, 65, .14); }
#TriangleTable td[contenteditable="true"]:focus {
    background: #fffdf7; outline: 0;
    box-shadow: inset 0 0 0 2px var(--ochre);
    caret-color: var(--sanguine);
}
#TriangleTable td[contenteditable="false"] { background: rgba(86, 160, 138, .07); font-weight: 500; }

/* The CHECK cell. AIP.js replaces the whole class attribute here, so key off
   the id and re-skin Bootstrap's two utility colors rather than adding one. */
#TriangleTable td[id^="Check"] { cursor: pointer; font-weight: 600; letter-spacing: .1em; font-size: .74rem; }
#TriangleTable td[id^="Check"]:hover { background: rgba(47, 122, 99, .16); }
/* color for every green element; the 1rem bump only for the master row and
   the CHECK/🗸 cells — NOT the thead § anchors, which size themselves */
#TriangleTable .text-success { color: var(--verdigris-dk) !important; }
#TriangleTable tr.text-success td, #TriangleTable td.text-success { font-size: 1rem; }
#TriangleTable .text-danger { color: var(--sanguine-dk) !important; }

/* ══ PART 3 — the findings sheet ══════════════════════════════════════════ */
#Part3 > div {
    max-width: 980px;
    padding: 15px 22px; margin: 0 !important;
    background: var(--sheet); color: var(--ink);
    border-left: 1px solid var(--sheet-edge); border-right: 1px solid var(--sheet-edge);
    border-bottom: 1px solid rgba(90, 98, 112, .18);
    /* laid paper */
    background-image: repeating-linear-gradient(0deg,
        rgba(90, 98, 112, .035) 0 1px, transparent 1px 6px);
    transition: background-color .25s ease;
}
#Part3 > div:first-of-type { border-top: 3px solid var(--verdigris); }
#Part3 > div:last-of-type { border-bottom: 1px solid var(--sheet-edge); box-shadow: 0 18px 40px rgba(0, 0, 0, .40); }
#Part3 > div:hover { background-color: #fffdf8; }
#Part3 p { margin: 0; font-size: 1rem; line-height: 1.9; }
#Part3 i { font-family: var(--disp); font-style: italic; font-weight: 600; color: var(--sanguine-dk); }
#Part3 input {
    width: 13ch; padding: 2px 6px;
    background: transparent; color: var(--sanguine-dk);
    border: 0; border-bottom: 2px solid rgba(90, 98, 112, .45);
    font: 500 .95rem/1.4 var(--mono); caret-color: var(--sanguine);
}
#Part3 input:focus { outline: 0; border-bottom-color: var(--ochre); background: rgba(217, 164, 65, .1); }
/* CheckAns() swaps a solved blank for a bare <b> — that's the ink going down. */
#Part3 b {
    padding: 0 .4em; color: var(--sanguine-dk);
    border-bottom: 2px solid var(--sanguine);
    font-family: var(--mono); font-weight: 500;
    animation: aip-ink .45s ease both;
}
@keyframes aip-ink { from { opacity: 0; transform: translateY(-3px); } }
#Part3 a {
    display: inline-block; padding: 3px 10px; margin-left: 4px;
    border: 1px solid var(--verdigris-dk); border-radius: 2px;
    color: var(--verdigris-dk) !important;
    font: 600 9.5px/1.6 var(--ui); letter-spacing: .16em; text-transform: uppercase;
    transition: background-color .16s ease, color .16s ease;
}
#Part3 a:hover { background: var(--verdigris-dk); color: #f2fbf7 !important; }

/* ══ PART 4 — the composition board ═══════════════════════════════════════ */
.art-grid {
    display: grid; grid-template-columns: minmax(280px, 340px) minmax(0, 1fr);
    gap: 26px; align-items: start;
}
.art-side { padding: 18px 20px 20px; }
.art-h { margin: 0 0 4px; font-family: var(--disp); font-weight: 700; font-size: 21px; color: var(--ink); }
.art-note { margin: 0 0 14px; font-size: .85rem; line-height: 1.5; color: var(--ink-2); }
#ArtTray { display: flex; flex-wrap: wrap; gap: 8px; margin: 0 0 14px; }
.art-chip {
    display: inline-flex; align-items: center; gap: 7px; padding: 5px 9px 5px 6px;
    background: #fff; border: 1px solid var(--sheet-edge); border-radius: 2px;
    font: 600 12px/1 var(--mono); color: var(--ink); cursor: pointer;
    transition: border-color .15s ease, transform .12s ease, box-shadow .2s ease;
}
.art-chip:hover:not(:disabled) {
    border-color: var(--azure); transform: translateY(-1px);
    box-shadow: 0 4px 12px rgba(59, 110, 165, .25);
}
.art-chip.is-used { opacity: .35; cursor: default; }
.art-chip svg { display: block; }
.art-chipsf { font-size: 10px; color: var(--ink-2); }
.art-empty { margin: 0; font-size: .85rem; font-style: italic; color: var(--ink-2); }

.art-tools { display: flex; gap: 6px; flex-wrap: wrap; margin: 0 0 10px; }
.art-tools button, #ArtClear {
    padding: 8px 11px; cursor: pointer;
    background: var(--sheet-2); color: var(--ink);
    border: 1px solid var(--sheet-edge); border-radius: 2px;
    font: 600 10.5px/1 var(--ui); letter-spacing: .09em; text-transform: uppercase;
    transition: border-color .15s ease, color .15s ease;
}
.art-tools button:hover:not(:disabled), #ArtClear:hover:not(:disabled) { border-color: var(--azure); color: var(--azure); }
.art-tools button:disabled, #ArtClear:disabled { opacity: .4; cursor: not-allowed; }
.art-keys { margin: 0 0 16px; font: 500 10.5px/1.7 var(--mono); color: var(--faint); }
.art-keys b { color: var(--ink-2); }
.art-actions { display: grid; gap: 8px; }
.art-actions .aip-btn { margin-left: 0; width: 100%; background: var(--azure); border-color: #2b5680; }
.art-actions .aip-btn:hover:not(:disabled) { background: #4a80b8; box-shadow: 0 6px 20px rgba(59, 110, 165, .35); }
#ArtMsg { margin: 12px 0 0; font-size: .84rem; line-height: 1.45; color: var(--ink-2); }
#ArtMsg.ok { color: var(--verdigris-dk); font-weight: 600; }
#ArtMsg.bad { color: var(--sanguine-dk); font-weight: 600; }

.art-boardwrap { padding: 16px 18px 16px; }
.art-boardhead {
    display: flex; gap: 16px; align-items: baseline; justify-content: space-between;
    flex-wrap: wrap; margin: 0 0 12px;
    font: 500 11.5px/1.55 var(--mono); color: var(--ink-2);
}
#ArtCount { flex: 0 0 auto; font-weight: 600; color: var(--ink); }
.art-snaptog {
    flex: 0 0 auto; display: inline-flex; align-items: center; gap: 6px;
    cursor: pointer; user-select: none;
    font: 600 10.5px/1 var(--ui); letter-spacing: .08em; text-transform: uppercase;
    color: var(--ink-2);
}
.art-snaptog input { accent-color: var(--azure); width: 14px; height: 14px; cursor: pointer; margin: 0; }
.art-scale { flex: 1 1 260px; max-width: 460px; }
.art-scale b { color: var(--sanguine-dk); }
/* 576 css px = 6in on a standard 96dpi screen = the 12in board at exactly 2:1 */
#ArtBoard {
    display: block; width: min(100%, 576px); aspect-ratio: 1 / 1; margin: 0 auto;
    touch-action: none;
    border: 1px solid var(--sheet-edge);
    box-shadow: 0 12px 30px rgba(0, 0, 0, .22);
}
.art-cutnote {
    margin: 12px auto 0; max-width: 576px;
    font: 500 10.5px/1.6 var(--mono); color: var(--faint);
}

/* ══ MODAL ════════════════════════════════════════════════════════════════ */
#myModal .modal-content {
    background: var(--sheet); color: var(--ink);
    border: 1px solid var(--sheet-edge); border-top: 4px solid var(--sanguine);
    border-radius: 2px; box-shadow: 0 30px 70px rgba(0, 0, 0, .55);
}
#myModal .modal-header { border-bottom: 1px solid rgba(90, 98, 112, .2); padding: 18px 22px 14px; }
#myModal .modal-title {
    font-family: var(--disp); font-weight: 700; font-size: 1.5rem; letter-spacing: .01em;
}
#myModal .modal-body { padding: 18px 22px; font-size: 1rem; line-height: 1.65; }
#myModal .modal-footer { border-top: 1px solid rgba(90, 98, 112, .2); padding: 12px 22px; }
#myModal .btn-danger {
    background: var(--wall-2); border: 1px solid var(--wall-3); color: var(--chalk);
    border-radius: 2px; padding: 8px 20px;
    font: 600 10.5px/1 var(--ui); letter-spacing: .16em; text-transform: uppercase;
}
#myModal .btn-danger:hover { background: var(--sanguine); border-color: var(--sanguine-dk); color: #fff8f4; }

/* ══ RESPONSIVE ═══════════════════════════════════════════════════════════ */
@media (max-width: 1180px) {
    /* Single column, source order: sheet, heading, ledger. */
    #Part2 { grid-template-columns: minmax(0, 1fr); }
    #CanvasContainer { grid-column: 1; grid-row: 1; position: static; margin: 24px auto 0; width: fit-content; }
    #Part2 > h1 { grid-row: 2; }
    #Part2 > #TriangleTable { grid-row: 3; }
    /* Part 4 stacks: board first, tray + tools beneath it */
    .art-grid { grid-template-columns: minmax(0, 1fr); }
    .art-boardwrap { order: -1; }
    /* Part 1 stacks: brief, entry card, then the sheet once START reveals it */
    #Part1 { grid-template-columns: minmax(0, 1fr); grid-template-rows: auto auto auto; }
    #Instructions0 { grid-column: 1; grid-row: 1; position: static; }
    #Part1 > #Tri0Input { grid-column: 1; grid-row: 2; }
    #ProvePanel { grid-column: 1; grid-row: 3; }
}
@media (max-width: 900px) {
    .aip-bar { gap: 12px; padding: 7px 14px; }
    .aip-steps { margin-left: 0; width: 100%; order: 3; }
    .aip-acts { order: 4; }
    .aip-sub { display: none; }
    #Part1, #Part2, #Part3 { padding-inline: 14px; }
    #ProvePanel { padding: 18px 16px 16px; }
    .tiq-row { font-size: 17px; }
    .tiq { font-size: 17px; }
    .tiq-simpwrap { margin-left: 0; }
    #BuildCanvas { height: 300px; }
    #TriangleTable { font-size: .74rem; }
    #TriangleTable td { padding: 7px 3px; }
    /* thead carries its own font shorthand, so shrink it here explicitly */
    #TriangleTable thead td { font-size: 12px; letter-spacing: .05em; }
    #Part3 > div { padding: 13px 15px; }
}
@media (max-width: 560px) {
    /* The wordmark is the widest fixed thing in the bar — let it give. */
    .aip-owl img { width: 44px; }
    .aip-mark { width: 34px; height: 31px; }
    .aip-name { font-size: 19px; white-space: normal; }
    .aip-wordmark { column-gap: 8px; }
    .aip-step { padding: 7px 10px; letter-spacing: .08em; }
    .aip-act, .aip-login { padding: 7px 9px; letter-spacing: .1em; }
    #Tri0Input { padding: 16px 15px 18px; }
    .aip-startrow { gap: 10px; padding: 12px 13px; }
    .aip-btn { margin-left: 0; width: 100%; }
}

/* ══ REDUCED MOTION ═══════════════════════════════════════════════════════ */
@media (prefers-reduced-motion: reduce) {
    body::after, .aip-mark .am-t, .aip-mark .am-v { animation: none; }
    .aip-mark .am-t { stroke-dashoffset: 0; }
    #Part1, #Part2, #Part3, #Part1 h1::before, #Part2 h1::before, #Part3 h1::before, #Part3 b {
        animation: none;
    }
}

/* ══ PRINT ════════════════════════════════════════════════════════════════
   Printing runs through Print(), which opens its own window — the page itself
   stays out of the way (unchanged from the original sheet). */
@media print {
    body { visibility: hidden; }
    canvas { break-after: always; }
}
