/* ============================================================================
   shape-common.css — the site's SHAPE SYSTEM (default since 2026-08)
   ----------------------------------------------------------------------------
   Linked statically in every page head; active under html[data-shape],
   stamped pre-paint by the FOUC guard and kept live by theme-common.js.
   Modes (localStorage "chunimaru.shape", ?shape=0|1|2, account "Legacy
   design" toggle):
     - "mixed"  (DEFAULT, data-shape="mixed"): sharp structure, soft
       touchables — section 3 below.
     - legacy   (no data-shape attribute): the pre-overhaul pill look; this
       file goes inert.
     - "square" (data-shape="square", dev preview only): everything sharp.
   Mechanically this is still an override layer (blanket + carve-backs +
   mode rules); a future cleanup may bake the mixed radii into component
   styles and shrink this file, but that is cosmetics, not behavior.

   HARD RULE: the PNG-rendered sheets (.export-sheet, .record-card-sheet)
   are DESIGN-FROZEN. Every selector in this file carries a :where(:not())
   guard against their subtrees — keep it on anything you add. No shape
   rule may ever change a rendered export.
   ============================================================================ */

/* ---- 1) Blanket de-pill: everything goes square in the preview ----
   :where() keeps the exclusions at zero specificity so the carve-back
   exceptions below still win. The export/record-card sheets are excluded
   from the blanket entirely: they rasterize to PNG and their look is
   frozen by contract — the preview layer must never leak into exports. */
html[data-shape] *:where(:not(.export-sheet, .export-sheet *, .record-card-sheet, .record-card-sheet *)),
html[data-shape] *:where(:not(.export-sheet, .export-sheet *, .record-card-sheet, .record-card-sheet *))::before,
html[data-shape] *:where(:not(.export-sheet, .export-sheet *, .record-card-sheet, .record-card-sheet *))::after {
    border-radius: 0 !important;
}

/* ============================================================================
   2) Sanctioned exceptions (each needs !important to beat the blanket rule)
   ============================================================================ */

/* ---- Circular-by-geometry elements: never flatten ----
   A spinner or orbit rendered square becomes a rotating diamond. Anything
   that is a circle by FUNCTION (conic borders, rotation animations, orbital
   decor) must be listed here — name-based matching alone misses pseudo-
   element spinners, so new spinners need an explicit entry. */
html[data-shape] .blocking-spinner:where(:not(.export-sheet, .export-sheet *, .record-card-sheet, .record-card-sheet *)),
html[data-shape] [class*="spinner"]:where(:not(.export-sheet, .export-sheet *, .record-card-sheet, .record-card-sheet *)),
html[data-shape] [class*="spinner"]:where(:not(.export-sheet, .export-sheet *, .record-card-sheet, .record-card-sheet *))::before,
html[data-shape] [class*="spinner"]:where(:not(.export-sheet, .export-sheet *, .record-card-sheet, .record-card-sheet *))::after,
html[data-shape] .download-button.is-preparing:where(:not(.export-sheet, .export-sheet *, .record-card-sheet, .record-card-sheet *))::before, /* export.html prepare spinner */
html[data-shape] .universe-center-box:where(:not(.export-sheet, .export-sheet *, .record-card-sheet, .record-card-sheet *))::after            /* lverse orbital decor ring */ {
    border-radius: 50% !important;
}

/* ---- Avatars / profile images: stay fully round (50%) ---- */

/* Player profile photo + gradient shell — rating.html / past-rating.html.
   .has-frame swaps the shell for a frame PNG with its own silhouette, so the
   framed variant keeps the blanket 0 (the :not() leaves it untouched). */
html[data-shape] .profile-photo-shell:not(.has-frame):where(:not(.export-sheet, .export-sheet *, .record-card-sheet, .record-card-sheet *)),
html[data-shape] .profile-photo-shell:not(.has-frame):where(:not(.export-sheet, .export-sheet *, .record-card-sheet, .record-card-sheet *))::before,
html[data-shape] .profile-photo-shell:not(.has-frame) .profile-photo:where(:not(.export-sheet, .export-sheet *, .record-card-sheet, .record-card-sheet *)) {
    border-radius: 50% !important;
}

/* Contributor profile pictures — credits.html */
html[data-shape] .credit-avatar:where(:not(.export-sheet, .export-sheet *, .record-card-sheet, .record-card-sheet *)) {
    border-radius: 50% !important;
}

/* ---- Jacket art thumbnails: soft 3px so art doesn't read razor-edged ---- */

/* Records table jackets — records.html */
html[data-shape] .records-jacket-cell img:where(:not(.export-sheet, .export-sheet *, .record-card-sheet, .record-card-sheet *)),
html[data-shape] .records-jacket-placeholder:where(:not(.export-sheet, .export-sheet *, .record-card-sheet, .record-card-sheet *)) {
    border-radius: 3px !important;
}

/* Rating table jackets — rating.html / past-rating.html */
html[data-shape] .rating-jacket-frame img:where(:not(.export-sheet, .export-sheet *, .record-card-sheet, .record-card-sheet *)),
html[data-shape] .rating-jacket-placeholder:where(:not(.export-sheet, .export-sheet *, .record-card-sheet, .record-card-sheet *)) {
    border-radius: 3px !important;
}
/* ...except rating.html's phone card view, where the jacket becomes a
   full-bleed masked backdrop that must stay flush with the card edge. */
html[data-shape] .rating-table-wrapper.cm-table-cards .rating-jacket-frame img:where(:not(.export-sheet, .export-sheet *, .record-card-sheet, .record-card-sheet *)),
html[data-shape] .rating-table-wrapper.cm-table-cards .rating-jacket-placeholder:where(:not(.export-sheet, .export-sheet *, .record-card-sheet, .record-card-sheet *)) {
    border-radius: 0 !important;
}

/* Song catalog jackets — catalog.html */
html[data-shape] .cg-jacket:where(:not(.export-sheet, .export-sheet *, .record-card-sheet, .record-card-sheet *)) {
    border-radius: 3px !important;
}

/* Calculator chart jacket — calculator.html (widget reused on badge.html) */
html[data-shape] .calculator-jacket:where(:not(.export-sheet, .export-sheet *, .record-card-sheet, .record-card-sheet *)),
html[data-shape] .calculator-jacket img:where(:not(.export-sheet, .export-sheet *, .record-card-sheet, .record-card-sheet *)),
html[data-shape] .calculator-jacket-placeholder:where(:not(.export-sheet, .export-sheet *, .record-card-sheet, .record-card-sheet *)) {
    border-radius: 3px !important;
}

/* Badge-grind list thumbnails — calculator.html only; scoped by data-page
   because badge.html reuses .badge-grind-jacket as a full-bleed card decor
   (border-radius: 0 there) that must stay flush. */
html[data-shape] body[data-page="calculator"] .badge-grind-jacket:where(:not(.export-sheet, .export-sheet *, .record-card-sheet, .record-card-sheet *)),
html[data-shape] body[data-page="calculator"] .badge-grind-jacket img:where(:not(.export-sheet, .export-sheet *, .record-card-sheet, .record-card-sheet *)),
html[data-shape] body[data-page="calculator"] .badge-grind-jacket-placeholder:where(:not(.export-sheet, .export-sheet *, .record-card-sheet, .record-card-sheet *)) {
    border-radius: 3px !important;
}

/* Chart detail modal jacket — injected by chart-detail-modal.js on the pages
   that open it (records/rating/catalog/todo/constants/...) */
html[data-shape] .chart-detail-jacket:where(:not(.export-sheet, .export-sheet *, .record-card-sheet, .record-card-sheet *)),
html[data-shape] .chart-detail-jacket img:where(:not(.export-sheet, .export-sheet *, .record-card-sheet, .record-card-sheet *)),
html[data-shape] .chart-detail-jacket-placeholder:where(:not(.export-sheet, .export-sheet *, .record-card-sheet, .record-card-sheet *)) {
    border-radius: 3px !important;
}

/* Todo list entry + confirm dialog jackets — todo.html */
html[data-shape] .confirm-song-jacket:where(:not(.export-sheet, .export-sheet *, .record-card-sheet, .record-card-sheet *)),
html[data-shape] .entry-jacket:where(:not(.export-sheet, .export-sheet *, .record-card-sheet, .record-card-sheet *)) {
    border-radius: 3px !important;
}

/* Constants chart card jackets — constants.html */
html[data-shape] .constant-chart-jacket img:where(:not(.export-sheet, .export-sheet *, .record-card-sheet, .record-card-sheet *)),
html[data-shape] .constant-chart-jacket-placeholder:where(:not(.export-sheet, .export-sheet *, .record-card-sheet, .record-card-sheet *)) {
    border-radius: 3px !important;
}

/* Version diff row jackets — diff.html */
html[data-shape] .row-jacket:where(:not(.export-sheet, .export-sheet *, .record-card-sheet, .record-card-sheet *)),
html[data-shape] .row-jacket-placeholder:where(:not(.export-sheet, .export-sheet *, .record-card-sheet, .record-card-sheet *)) {
    border-radius: 3px !important;
}

/* WORLD'S END chart jackets — we.html */
html[data-shape] .we-jacket:where(:not(.export-sheet, .export-sheet *, .record-card-sheet, .record-card-sheet *)),
html[data-shape] .we-jacket-empty:where(:not(.export-sheet, .export-sheet *, .record-card-sheet, .record-card-sheet *)) {
    border-radius: 3px !important;
}

/* Overpower song jackets — overpower.html */
html[data-shape] .op-song-jacket:where(:not(.export-sheet, .export-sheet *, .record-card-sheet, .record-card-sheet *)) {
    border-radius: 3px !important;
}

/* ---- Tiny status dots (<= 10px): stay round or they read as pixels ----
   (The header account dot was removed from the site entirely — if a new
   status dot ever appears, its exception goes here.) */

/* ============================================================================
   3) MODE 2 — "mixed" (?shape=2): sharp structure, soft touchables
   ----------------------------------------------------------------------------
   The blanket above still zeroes everything, then these rules soften only what
   the hand touches. Hierarchy through radius: the bigger and more structural
   an element, the sharper it stays (site frame, panels, tables, cards, modals
   remain 0). Interactive controls 6px; micro chips/badges 4px; floating
   menus/popovers 8px; toggle knobs 4px inside their 6px tracks. Circles from
   section 2 stay circles in both modes.
   ============================================================================ */

/* interactive controls: 6px */
html[data-shape="mixed"] button:where(:not(.export-sheet, .export-sheet *, .record-card-sheet, .record-card-sheet *)),
html[data-shape="mixed"] input:where(:not(.export-sheet, .export-sheet *, .record-card-sheet, .record-card-sheet *)),
html[data-shape="mixed"] select:where(:not(.export-sheet, .export-sheet *, .record-card-sheet, .record-card-sheet *)),
html[data-shape="mixed"] textarea:where(:not(.export-sheet, .export-sheet *, .record-card-sheet, .record-card-sheet *)),
html[data-shape="mixed"] [class*="button"]:where(:not(.export-sheet, .export-sheet *, .record-card-sheet, .record-card-sheet *)),
html[data-shape="mixed"] [class*="-btn"]:where(:not(.export-sheet, .export-sheet *, .record-card-sheet, .record-card-sheet *)),
html[data-shape="mixed"] [class*="input"]:where(:not(.export-sheet, .export-sheet *, .record-card-sheet, .record-card-sheet *)),
html[data-shape="mixed"] [class*="select"]:where(:not(.export-sheet, .export-sheet *, .record-card-sheet, .record-card-sheet *)),
html[data-shape="mixed"] [class*="toggle"]:where(:not(.export-sheet, .export-sheet *, .record-card-sheet, .record-card-sheet *)),
html[data-shape="mixed"] [class*="switch"]:where(:not(.export-sheet, .export-sheet *, .record-card-sheet, .record-card-sheet *)),
html[data-shape="mixed"] [class*="segment"]:where(:not(.export-sheet, .export-sheet *, .record-card-sheet, .record-card-sheet *)),
html[data-shape="mixed"] [class*="close"]:where(:not(.export-sheet, .export-sheet *, .record-card-sheet, .record-card-sheet *)),
html[data-shape="mixed"] [class*="pager"]:where(:not(.export-sheet, .export-sheet *, .record-card-sheet, .record-card-sheet *)),
html[data-shape="mixed"] [class*="tab"]:not([class*="table"]):where(:not(.export-sheet, .export-sheet *, .record-card-sheet, .record-card-sheet *)),
html[data-shape="mixed"] .cta:where(:not(.export-sheet, .export-sheet *, .record-card-sheet, .record-card-sheet *)),
html[data-shape="mixed"] .cg-search:where(:not(.export-sheet, .export-sheet *, .record-card-sheet, .record-card-sheet *)),
html[data-shape="mixed"] .chuni-account:where(:not(.export-sheet, .export-sheet *, .record-card-sheet, .record-card-sheet *)),
html[data-shape="mixed"] .chart-detail-link:where(:not(.export-sheet, .export-sheet *, .record-card-sheet, .record-card-sheet *)),
html[data-shape="mixed"] .calculator-chart-link:where(:not(.export-sheet, .export-sheet *, .record-card-sheet, .record-card-sheet *)),
html[data-shape="mixed"] .mm-link:where(:not(.export-sheet, .export-sheet *, .record-card-sheet, .record-card-sheet *)) {
    border-radius: 6px !important;
}

/* micro identity: chips, tags, badges, pills, tokens, difficulty markers: 4px */
html[data-shape="mixed"] [class*="chip"]:where(:not(.export-sheet, .export-sheet *, .record-card-sheet, .record-card-sheet *)),
html[data-shape="mixed"] [class*="tag"]:where(:not(.export-sheet, .export-sheet *, .record-card-sheet, .record-card-sheet *)),
html[data-shape="mixed"] [class*="badge"]:where(:not(.export-sheet, .export-sheet *, .record-card-sheet, .record-card-sheet *)),
html[data-shape="mixed"] [class*="pill"]:where(:not(.export-sheet, .export-sheet *, .record-card-sheet, .record-card-sheet *)),
html[data-shape="mixed"] [class*="token"]:where(:not(.export-sheet, .export-sheet *, .record-card-sheet, .record-card-sheet *)),
html[data-shape="mixed"] [class*="combo"]:where(:not(.export-sheet, .export-sheet *, .record-card-sheet, .record-card-sheet *)),
html[data-shape="mixed"] .cg-diff:where(:not(.export-sheet, .export-sheet *, .record-card-sheet, .record-card-sheet *)),
html[data-shape="mixed"] .d-BAS:where(:not(.export-sheet, .export-sheet *, .record-card-sheet, .record-card-sheet *)),
html[data-shape="mixed"] .d-ADV:where(:not(.export-sheet, .export-sheet *, .record-card-sheet, .record-card-sheet *)),
html[data-shape="mixed"] .d-EXP:where(:not(.export-sheet, .export-sheet *, .record-card-sheet, .record-card-sheet *)),
html[data-shape="mixed"] .d-MAS:where(:not(.export-sheet, .export-sheet *, .record-card-sheet, .record-card-sheet *)),
html[data-shape="mixed"] .d-REM:where(:not(.export-sheet, .export-sheet *, .record-card-sheet, .record-card-sheet *)) {
    border-radius: 4px !important;
}

/* toggle knobs: one step tighter than their track */
html[data-shape="mixed"] [class*="toggle"]:where(:not(.export-sheet, .export-sheet *, .record-card-sheet, .record-card-sheet *))::after,
html[data-shape="mixed"] [class*="switch"]:where(:not(.export-sheet, .export-sheet *, .record-card-sheet, .record-card-sheet *))::after {
    border-radius: 4px !important;
}

/* floating surfaces (menus, popovers, help popups): 8px */
html[data-shape="mixed"] .chuni-features-panel:where(:not(.export-sheet, .export-sheet *, .record-card-sheet, .record-card-sheet *)),
html[data-shape="mixed"] [class*="popup"]:where(:not(.export-sheet, .export-sheet *, .record-card-sheet, .record-card-sheet *)),
html[data-shape="mixed"] [class*="popover"]:where(:not(.export-sheet, .export-sheet *, .record-card-sheet, .record-card-sheet *)),
html[data-shape="mixed"] [class*="dropdown"]:where(:not(.export-sheet, .export-sheet *, .record-card-sheet, .record-card-sheet *)) {
    border-radius: 8px !important;
}
