/* ============================================================================
   project-page.css

   The pieces a research project page needs and `style_new.css` does not carry:
   a framed figure, an embedded demo, a button that is not a link yet, a folded
   licence, and the small print under a figure or a control.

   Loaded AFTER style_new.css. It adds classes; it never redefines one of the
   site's own (.page-title, .page-author, .project-button, .page-cite are all
   still the shared sheet's). Nearly every value below is one of that sheet's
   semantic tokens, so both themes follow from its one dark block.

   The exceptions are four surfaces that are theme-INVARIANT on purpose, and
   they are the only literals here:
     - .fig-onwhite and .demo-paper are white in both themes, because what sits
       on them is an image or an iframe with black ink baked into it. Following
       the theme would put that ink on a dark ground.
     - .demo-window is near-black in both, because a 3D viewer fills it and the
       frame should read as the viewer's own surround.
     - .demo-fullscreen-close is a dark pill with a white glyph in both, because
       it floats over a demo whose colours this sheet does not control.
   A token would not help any of these: a token that has the same value in both
   blocks is a constant wearing a costume.

   Used by: Neural_Surface_Potential, Fast_Splat_Morphing,
   Boundary_Power_Method, Table_Clearing_Cat.
   ============================================================================ */


/* --- Figures ---------------------------------------------------------------
   A figure is a bordered box with the caption inside it, on its own footer, so
   a teaser and its sentence read as one object and never drift apart across a
   column break. Same treatment as the GravoTet page. */

.fig-frame {
    border: 1px solid var(--frame-hairline);
    border-radius: 10px;
    overflow: hidden;
    background: var(--surface-inset);
}

.fig-frame > img {
    display: block;
    width: 100%;
    border-radius: 0;
}

.fig-caption {
    background: var(--surface-caption);
    border-top: 1px solid var(--frame-hairline);
    padding: 9px 14px;
    font-size: 0.82rem;
    color: var(--text-muted-strong);
    text-align: left;
    line-height: 1.45;
}

/* A figure on a WHITE ground, whether it is a plot or a render: white behind
   it in both themes, because the ink and the axis labels are baked into the
   image as black and a dark surface underneath them is unreadable. The test is
   the image's own background, not what it depicts. Named for what it does: it
   is a white mat, not a lightbox, and nothing here opens an overlay. */
.fig-frame.fig-onwhite { background: #ffffff; }
.fig-frame.fig-onwhite > img { background: #ffffff; }

/* A dense multi-panel figure is unreadable on a phone, where it lands about
   330px wide with 3px axis labels. Wrapping it in a link to the file itself
   gives a tap a way out, at the cost of nothing. */
.fig-frame > a { display: block; }


/* --- The lead paragraph ----------------------------------------------------
   Two or three sentences under the buttons, set slightly larger than body
   text: it is the one thing a visitor who reads nothing else will read. */

.lead-desc {
    font-size: 1.08rem;
    line-height: 1.6;
    max-width: 62rem;
    margin-left: auto;
    margin-right: auto;
}


/* --- Buttons ---------------------------------------------------------------
   A pending button is the same shape as a real one and visibly not pressable,
   so the page can promise a link before the link exists without ever looking
   like a dead one. It is a <span>, not an <a>: there is nothing to follow. */

.project-button.pending {
    /* Not dimmed. Halving the opacity put the label under 4.5:1 in both themes
       (measured: 2.99:1 light, 3.97:1 dark), and this text is meant to be read.
       An outline says "not a link yet" without touching the contrast.
       pointer-events stays ON so the title attribute can still explain why. */
    background-color: transparent;
    color: var(--text-muted-strong) !important;
    border: 1px dashed var(--frame-edge);
    outline: none;
    opacity: 1;
    filter: none;
    cursor: default;
}

.project-button.pending:hover {
    background-color: transparent;
    box-shadow: none;
    transform: none;
    color: var(--text-muted-strong) !important;
}

/* The soon-tag rides inside the button rather than after it, so the row keeps
   one rhythm whether or not a given link has landed. */
.btn-soon {
    font-size: 0.72em;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    opacity: 0.85;
    margin-left: 0.35em;
}


/* --- The demo window -------------------------------------------------------
   Framed like the figures, kept to the page's content width so there are
   gutters left and right to scroll past it: a wheel over a 3D viewer zooms.
   Same window the Fractal Splats page uses. */

.demo-window {
    position: relative;
    width: 100%;
    /* --demo-h lets a page give a taller demo the room it needs without
       restating the rule. A viewer that is one 3D canvas is happy at the
       default; an instrument panel with controls, plots and a readout is not. */
    height: var(--demo-h, clamp(460px, 68vh, 760px));
    border: 1px solid var(--frame-edge);
    border-radius: 14px;
    overflow: hidden;
    box-shadow: var(--shadow-frame);
    background: #05070b;
}

/* A demo that draws on white in both themes: the solver panels plot black ink
   on a white ground from inside their own canvases, so the frame commits to
   white rather than putting a near-black surround around a white sheet. Making
   the demo itself follow the page theme would mean re-colouring its canvases,
   which belongs in the research repo and not in a copy of it. */
.demo-window.demo-paper { background: #ffffff; }

/* On phones the embed is shorter than the viewport, so there is always page
   above and below it to start a scroll from. The viewers leave the vertical
   swipe to the page themselves; this is the second line of defence. */
@media (max-width: 767px) {
    .demo-window { height: var(--demo-h-sm, clamp(340px, 56vh, 520px)); }
}

.demo-window iframe {
    display: block;
    width: 100%;
    height: 100%;
    border: 0;
}

/* Full screen is the same iframe promoted to a fixed overlay, so the demo
   keeps running in place: nothing reloads and nothing is loaded twice. */
.demo-window.fullscreen {
    position: fixed;
    inset: 0;
    z-index: 3000;
    height: auto;
    border: 0;
    border-radius: 0;
    box-shadow: none;
}

body.demo-fullscreen { overflow: hidden; }

.demo-fullscreen-close {
    position: absolute;
    top: 10px;
    right: 10px;
    z-index: 20;
    display: none;
    width: 38px;
    height: 38px;
    border-radius: 50%;
    border: 1px solid rgba(255, 255, 255, 0.4);
    background: rgba(10, 10, 16, 0.65);
    color: #fff;
    font-size: 20px;
    line-height: 1;
    cursor: pointer;
}

.demo-fullscreen-close:hover { background: rgba(10, 10, 16, 0.9); }
.demo-window.fullscreen .demo-fullscreen-close { display: block; }



/* --- Folded sections -------------------------------------------------------
   A <details> that IS the card, with its summary as the header row inside it,
   so opening one does not leave its contents spilling out below a box that
   closed above them. Lifted from the splat-dataset page, which is where the
   licence text was first folded away. */

.card-section {
    border: 1px solid rgba(var(--edge-rgb), 0.1);
    border-radius: 14px;
    background: var(--surface-row);
    padding: 1rem 1.2rem;
}

.card-section > :is(h3, h4) { color: var(--brand-ink-heading); }

.fold { padding: 0; }

.fold > summary {
    display: flex;
    align-items: baseline;
    gap: 0.7rem;
    cursor: pointer;
    list-style: none;
    padding: 1rem 1.2rem;
    border-radius: 13px;
    touch-action: manipulation;
}

/* Closed, the summary is the whole card and must round with it; open, its
   bottom corners have content under them and must not. */
.fold[open] > summary { border-radius: 13px 13px 0 0; }
.fold > summary::-webkit-details-marker { display: none; }
.fold > summary:hover { background: var(--surface-row-hover); }

.fold > summary:focus-visible {
    outline: 3px solid var(--focus-ring);
    outline-offset: -3px;
}

.fold > summary :is(h3, h4) { color: var(--brand-ink-heading); }

.fold > summary::after {
    content: '';
    margin-left: auto;
    align-self: center;
    width: 0.6em;
    height: 0.6em;
    border-right: 2px solid currentColor;
    border-bottom: 2px solid currentColor;
    transform: rotate(45deg) translate(-0.1em, -0.1em);
    transition: transform 0.15s ease;
    opacity: 0.65;
}

.fold[open] > summary::after {
    transform: rotate(-135deg) translate(-0.1em, -0.1em);
}

.fold-body { padding: 0 1.2rem 1.1rem; }
.fold-hint { font-size: 0.85rem; color: var(--text-muted); }


@media (prefers-reduced-motion: reduce) {
    .fold > summary::after { transition: none; }
}

/* An aside inside prose: a line of method that is worth stating exactly and is
   not worth making anyone read. Lighter than a .fold, which is a whole card. */
details.aside-note {
    display: block;
    max-width: 100%;
    border: 1px solid var(--border-hairline-soft);
    border-radius: 8px;
    padding: 6px 12px;
    margin: 14px 0;
    background: var(--surface-quiet-2);
}

details.aside-note summary {
    cursor: pointer;
    font-weight: 600;
    color: var(--text-muted-strong);
    font-size: 0.95rem;
}

details.aside-note[open] summary { margin-bottom: 6px; }
details.aside-note p { margin-bottom: 6px; font-size: 0.95rem; }
details.aside-note ul { margin-bottom: 0; padding-left: 1.2rem; font-size: 0.95rem; }
details.aside-note li { margin-bottom: 0.15rem; }


/* --- Small print -----------------------------------------------------------
   Under a control, a figure, or a licence bullet. */

.small-note {
    font-size: 0.85rem;
    color: var(--text-muted-strong);
    line-height: 1.5;
}

.lic-list { padding-left: 1.15rem; }
.lic-list > li { margin-bottom: 0.45rem; }


/* --- Headline numbers ------------------------------------------------------
   Three or four measured results, each with the unit it was measured in. They
   sit under the teaser, so the claim and the picture arrive together. */

.fact-row {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 0.8rem;
}

.fact {
    flex: 1 1 12rem;
    max-width: 16rem;
    border: 1px solid rgba(var(--edge-rgb), 0.12);
    border-radius: 12px;
    background: var(--surface-row);
    padding: 0.75rem 0.9rem;
    text-align: center;
}

.fact-value {
    display: block;
    font-size: 1.5rem;
    font-weight: 700;
    line-height: 1.15;
    color: var(--brand-ink-heading);
    font-variant-numeric: tabular-nums;
}

.fact-label {
    display: block;
    margin-top: 0.2rem;
    font-size: 0.8rem;
    color: var(--text-muted-strong);
    line-height: 1.35;
}



/* --- Subheads ---------------------------------------------------------------
   A subhead inside a section is one level below that section's <h2>, so it is
   an <h3> and the document outline has no gap in it. It is sized like the
   site's <h4>, because that is the weight the older project pages set these at
   and the rhythm of the page should not change to fix an outline. */

h3.subhead {
    font-size: 1.5rem;
    font-weight: 500;
}
