/* ───────────── MythosLoom theme: dark parchment-and-ember ───────────── */
/*
   Taken from the prototype's app.css so the two look like one product. Only what Phase 1 renders is
   here — the prototype's stat blocks, spell cards, initiative rows, plot clocks, meters and table-view
   styles are left behind rather than carried over as dead rules. They come back with the screens that
   need them, in Phase 2 and Phase 3.

   The custom properties are the whole theme. Anything new should use them rather than a literal colour;
   a hard-coded hex is how a palette stops being a palette.

   #101 tried the mockup's light parchment across the whole product and it was rejected on sight: the
   argument for it was that the character sheet prints on paper and a dark screen makes it two documents,
   which is true and is not worth the product being a colour nobody wanted to look at. The typography from
   that experiment stayed. So did the four bugs it exposed, all of which were only ever invisible rather
   than absent — the comments that mention a light ground are describing how each was found.

   Darkest where you read, lighter where something is raised. The roles matter as much as the values: the
   light version of this had to invert them as well, and putting the sidebar and the form fields on the
   wrong side of that was the first thing that went wrong.
*/
:root {
    --bg: #0f0e13;          /* the page, and the recessed ground of a form field */
    --bg-2: #17161d;        /* the sidebar */
    --bg-3: #1f1d27;        /* an inset or a card within a panel */
    --panel: #1b1a22;       /* a raised panel */
    --border: #2d2b38;
    --border-strong: #3f3c4e;
    --text: #e8e3d8;
    --muted: #9c97a8;
    --accent: #d9822b;      /* ember */
    --accent-hover: #f0a050;
    --accent-soft: rgba(217, 130, 43, .15);
    --on-accent: #1a0f05;   /* text on an accent fill */
    --accent-2: #8b5cf6;    /* arcane violet */
    --danger: #d64545;
    --ok: #3fae6a;
    --warn: #e0b341;
    --radius: 10px;

    /*
       Cinzel is inscriptional: all capitals, no italic, cut for carving rather than reading. It is a
       nameplate face and is used as one — headings only, never a sentence. It was named here from the
       start and never loaded, so every heading in the product rendered in Palatino until #101; the
       @font-face block below is what made the declaration true.
    */
    --font-display: "Cinzel", "Palatino Linotype", "Book Antiqua", Georgia, serif;
    --font-body: "EB Garamond", Georgia, "Times New Roman", serif;

    /*
       A sans for the small print: field labels, table headings, the letterspaced metadata under a card.
       Garamond has a small x-height and turns to mush below about 13px, which is exactly the size those
       are. Two faces doing two jobs rather than one doing both badly.
    */
    --font-ui: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
}

/*
   Self-hosted, latin subset only — see wwwroot/fonts/README.md for why, and for the OFL licences that
   have to travel with the files. All three are variable fonts, so one file covers the whole weight range.

   They are declared here rather than in sheet.css because App.razor loads this file on every page, the
   printed sheet included: PrintLayout strips the chrome, not the head. A browser downloads a face only
   where something uses it, so the pages that never set one pay nothing for the declaration.
*/
@font-face {
    font-family: "Cinzel";
    font-style: normal;
    font-weight: 400 700;
    font-display: swap;
    src: url("fonts/cinzel-latin.woff2") format("woff2");
}

/*
   The sheet's label face (#162): section headings, the small letterspaced capitals over a number, the
   character's name. A condensed grotesque against the serif everything else is read in — it is what makes
   the sheet scannable without a single box or rule being added, and it is the one thing #152 was set in
   that this could not have until the file was here.
*/
@font-face {
    font-family: "Archivo Narrow";
    font-style: normal;
    font-weight: 400 700;
    font-display: swap;
    src: url("fonts/archivonarrow-latin.woff2") format("woff2");
}

@font-face {
    font-family: "EB Garamond";
    font-style: normal;
    font-weight: 400 600;
    font-display: swap;
    src: url("fonts/ebgaramond-latin.woff2") format("woff2");
}

@font-face {
    font-family: "EB Garamond";
    font-style: italic;
    font-weight: 400 600;
    font-display: swap;
    src: url("fonts/ebgaramond-italic-latin.woff2") format("woff2");
}

html, body { background: var(--bg); color: var(--text); font-family: var(--font-body); }
/* Garamond runs small for its point size, so the base is nudged up rather than every rule being resized. */
body { min-height: 100vh; font-size: 1.05rem; line-height: 1.55; }
a { color: var(--accent); text-decoration: none; }
a:hover { color: var(--accent-hover); }
h1, h2, h3, h4, .brand { font-family: var(--font-display); font-weight: 600; letter-spacing: .03em; color: var(--text); }
h1 { font-size: 1.9rem; } h2 { font-size: 1.4rem; } h3 { font-size: 1.15rem; }
h1:focus { outline: none; }
::selection { background: var(--accent-2); color: white; }

/* layout */
.shell { display: grid; grid-template-columns: 240px 1fr; min-height: 100vh; }
/*
   A column, so the footer can be pushed to the bottom of it rather than sitting under the last link
   (#406). The nav grows to fill whatever the links do not use, and the footer inside it takes the slack.
*/
.sidebar { background: var(--bg-2); border-right: 1px solid var(--border); padding: 1rem .75rem; position: sticky; top: 0; height: 100vh; overflow-y: auto; display: flex; flex-direction: column; }
.sidebar .nav.flex-column { flex: 1 1 auto; }
.nav-footer { margin-top: auto; padding-top: .9rem; border-top: 1px solid var(--border); }
/*
   Quiet on purpose. It is there to be found when somebody asks "which version are you on", not to be
   read on the way past.
*/
.nav-version { font-family: var(--font-ui); font-size: .7rem; letter-spacing: .08em; color: var(--muted); padding: .5rem .6rem 0; }
.content { padding: 1.5rem 2rem 4rem; max-width: 1400px; }
/*
   Narrow: the sidebar becomes a bar across the top, not a column stacked above the page (#382).

   Dropping to one grid column was only half a responsive layout. Everything in the sidebar kept its
   vertical arrangement, so a phone got the wordmark, the navigation, three administration links, the
   account block, a full-width Log out button and two About links — and only then the page. On the
   guided builder, where the whole design is one question at a time, the question began around 600px
   down and did so again on every step.

   Horizontal and scrollable rather than a disclosure. A <details> would be the honest markup for a
   menu that opens, but "collapsed on a phone, open on a desktop" means overriding the closed state
   from a media query, which is exactly the part of <details> that is not dependable across browsers.
   A row that scrolls needs no such trick, keeps every link one tap away, and costs one line of height.

   The section headings go. They label groups that only read as groups in a column, and the links under
   them — Accounts, Feature flags, Audit log, Terms, Privacy — say what they are without a heading over
   them. Sticky, so it stays reachable without scrolling back up.
*/
@media (max-width: 900px) {
    .shell { grid-template-columns: 1fr; }

    .sidebar {
        position: sticky; top: 0; z-index: 10; height: auto;
        border-right: none; border-bottom: 1px solid var(--border);
        padding: .4rem .75rem;
        display: flex; align-items: center; gap: .5rem;
        overflow-x: auto; overflow-y: hidden;
    }

    .sidebar .brand { padding: 0 .4rem 0 0; font-size: 1rem; white-space: nowrap; }
    .sidebar .brand small { display: none; }

    .sidebar .nav.flex-column { flex-direction: row !important; align-items: center; flex-wrap: nowrap; }
    .sidebar .nav-section { display: none; }

    /*
       display: contents, so Terms, Privacy and the version join the row as siblings of the other links
       rather than as one block wedged into it. Nothing to push down to here, so the separator goes too.
    */
    .sidebar .nav-footer { display: contents; }
    .sidebar .nav-version { padding: 0 .4rem; white-space: nowrap; }
    .sidebar .nav a { padding: .3rem .5rem; font-size: .85rem; white-space: nowrap; }

    .sidebar form { margin: 0; }
    .sidebar form .btn { width: auto !important; margin-top: 0 !important; padding: .25rem .6rem; }

    .content { padding: 1rem; }
}

.brand { font-size: 1.25rem; color: var(--accent); display: block; padding: .25rem .5rem 1rem; }
.brand small { display: block; font-family: var(--font-ui); font-size: .7rem; color: var(--muted); letter-spacing: .1em; text-transform: uppercase; }
.nav-section { font-family: var(--font-ui); font-size: .7rem; text-transform: uppercase; letter-spacing: .12em; color: var(--muted); padding: .9rem .5rem .3rem; }
.nav a { display: flex; align-items: center; gap: .55rem; padding: .45rem .6rem; border-radius: 8px; color: var(--text); font-size: .93rem; }
.nav a:hover { background: var(--bg-3); }
.nav a.active { background: var(--accent-soft); color: var(--accent); }
/*
   Icons are SVG since #106, sized in em so they scale with whatever text they sit beside, and stroked in
   currentColor so an active navigation item's ember reaches them. They were emoji, which could do
   neither.
*/
.ico { width: 1.15em; height: 1.15em; flex: none; vertical-align: -0.18em; }
.nav a .ico { opacity: .85; }
.nav a.active .ico, .nav a:hover .ico { opacity: 1; }
.ico-lg { width: 1.7rem; height: 1.7rem; color: var(--accent); }

/* Bootstrap's .text-muted is its own grey, chosen for its own palette rather than this one. Kept pointed
   at the theme's muted colour so there is one answer to what muted means. It mattered more when the
   surfaces were dark — Bootstrap's near-black muted was invisible on them, which is what #93 found — and
   it still matters now for the same reason in reverse: two greys is one grey too many. */
.text-muted { color: var(--muted) !important; }

/* panels & cards */
.panel { background: var(--panel); border: 1px solid var(--border); border-radius: var(--radius); padding: 1rem 1.15rem; }
.panel + .panel { margin-top: 1rem; }
.panel-title { display: flex; justify-content: space-between; align-items: center; margin-bottom: .75rem; }
.panel-title h2, .panel-title h3 { margin: 0; }
.grid { display: grid; gap: 1rem; }
.grid-2 { grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); }
.grid-3 { grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); }
.card { color: var(--text); --bs-card-bg: var(--bg-3); background: var(--bg-3); border: 1px solid var(--border); border-radius: var(--radius); padding: .9rem 1rem; transition: border-color .15s; }
.card:hover { border-color: var(--border-strong); }
.muted { color: var(--muted); }
.small { font-size: .85rem; }
.tiny { font-size: .75rem; }
.mono { font-family: ui-monospace, Menlo, Consolas, monospace; }
.stack { display: flex; flex-direction: column; gap: .5rem; }
/* A horizontal group of controls. Deliberately NOT called .row.
   The prototype redefines Bootstrap's .row as a flex row and neutralises its gutters. That is fine in a
   project whose own markup uses it that way, and wrong here: the Identity account pages are laid out with
   Bootstrap's grid, and overriding .row flattened their columns so content ran off the side of the page.
   A separate name leaves the grid alone. */
.inline-row { display: flex; gap: .5rem; align-items: center; flex-wrap: wrap; }
.inline-row > .spacer { flex: 1 1 auto; }
.inline-row.between { justify-content: space-between; }
.spacer { flex: 1; }
hr { border-color: var(--border); opacity: 1; }

/* forms */
/*
   Tick boxes and radios are excluded, and the exclusion is the point. This rule uses the `background`
   shorthand with !important, which sets background-image to none as well as the colour — and a checked
   box is drawn by Bootstrap as a tick in a background image. Every checkbox in the application rendered
   as an empty box whether or not it was ticked: the equipment a character was wearing, the sections of
   the sheet to fill in, "remember me" on the login page. It was wrong on the dark theme too and simply
   did not look wrong, because an unstyled box on a dark ground looks like a box.
*/
input:not([type="checkbox"]):not([type="radio"]), select, textarea, .form-control, .form-select {
    background: var(--bg) !important; color: var(--text) !important; border: 1px solid var(--border) !important; border-radius: 8px !important;
}
input:focus, select:focus, textarea:focus, .form-control:focus, .form-select:focus { outline: none; border-color: var(--accent) !important; box-shadow: 0 0 0 3px var(--accent-soft) !important; }
label { font-family: var(--font-ui); font-size: .78rem; color: var(--muted); text-transform: uppercase; letter-spacing: .08em; margin-bottom: .2rem; display: block; }
.field { margin-bottom: .7rem; }
.form-check-input { background-color: var(--bg); border-color: var(--border-strong); }
.form-check-input:checked { background-color: var(--accent); border-color: var(--accent); }
.form-check-input:focus { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
.form-check-label { text-transform: none; letter-spacing: 0; font-size: .9rem; color: var(--text); display: inline; }

/*
   A <label> is not always a field caption. Bootstrap's btn-check pattern makes an entire card a label —
   which is how the builder draws a species or a class — and the rule above was uppercasing everything
   inside one, the ruleset's own words included: "Choose 1 of 18" arrived as "CHOOSE 1 OF 18" and a size
   as "MEDIUM, SMALL". Uppercase is for the small print, not for content.
*/
label.card, label.btn, label.nav-link {
    font-family: inherit; text-transform: none; letter-spacing: normal; font-size: inherit;
    color: inherit; margin-bottom: 0;
}

/*
   And the focus ring has to go on the label too, for the other half of the same arrangement (#381).

   btn-check hides the input — it is clipped to nothing, which is how an entire card becomes a radio
   button — so the element that holds the focus is the one element that cannot show it. Every rule above
   draws focus on the input, so the builder's largest and most-used control drew none at all: tab onto a
   class and the browser agrees it is focused, `:focus-visible` matches, and nothing on the screen moves.
   A keyboard player could reach the twelve classes and not see which one they were on.

   An outline rather than this file's usual border-plus-halo. The halo is a 15% wash that reads as a glow
   beside a field's solid accent border; on its own against a dark card it is not a focus indicator, and
   WCAG 2.4.7 wants one that can be seen. The ember at full strength, offset clear of the card's own
   border, is unambiguous and matches the colour that already means "this one".

   :focus-visible and not :focus, so clicking a card with a mouse does not leave a ring behind it.
*/
.btn-check:focus-visible + label {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}

/*
   Bootstrap's .border-primary is Bootstrap's blue, which belongs to neither this palette nor the one
   before it. The builder marks a chosen option with it, so the one card on the screen that is supposed
   to say "this one" said it in a colour from another product.
*/
.border-primary { border-color: var(--accent) !important; }
.text-primary { color: var(--accent) !important; }
.form-text { color: var(--muted); font-size: .85rem; }
textarea { min-height: 90px; }

/* The floating-label forms from the Identity scaffold sit badly against uppercase muted labels, so the
   label reverts to ordinary text inside them rather than every account page being rewritten. */
.form-floating > label { text-transform: none; letter-spacing: 0; color: var(--muted); }

/* buttons */
/* Buttons carry the sans: a button is a label, not prose, and Garamond's small caps read as decoration
   at button size. */
.btn { font-family: var(--font-ui); border-radius: 8px; font-weight: 500; border: 1px solid transparent; }
.btn-primary { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
.btn-primary:hover { background: var(--accent-hover); border-color: var(--accent-hover); color: var(--on-accent); }
.btn-outline-primary { background: transparent; border-color: var(--accent); color: var(--accent); }
.btn-outline-primary:hover { background: var(--accent); color: var(--on-accent); }
.btn-outline-secondary, .btn-ghost { background: transparent; border-color: var(--border); color: var(--text); }
.btn-outline-secondary:hover, .btn-ghost:hover { background: var(--bg-3); border-color: var(--border-strong); color: var(--text); }
.btn-danger, .btn-outline-danger { background: transparent; border-color: var(--danger); color: var(--danger); }
.btn-danger:hover, .btn-outline-danger:hover { background: var(--danger); color: var(--on-accent); }
.btn-outline-success { background: transparent; border-color: var(--ok); color: var(--ok); }
.btn-outline-success:hover { background: var(--ok); color: var(--on-accent); }
.btn-link { color: var(--accent); }
.btn-sm { font-size: .8rem; padding: .25rem .6rem; }

/* The account pages use nav-pills, whose active state is a Bootstrap colour that belongs to neither the
   light theme it assumes nor this one. Matched to the sidebar so the two navigations agree. */
.nav-pills .nav-link { color: var(--text); border-radius: 8px; }
.nav-pills .nav-link:hover { background: var(--bg-3); }
.nav-pills .nav-link.active { background: var(--accent-soft); color: var(--accent); }

/* badges & tags */
.badge { font-family: var(--font-ui); border-radius: 6px; font-weight: 500; padding: .25em .5em; }

/*
   Bootstrap's semantic backgrounds are Bootstrap's colours. The sheet marks a proficient save with one
   and the builder colours its findings by severity with the rest, so leaving them alone put a grey from
   another palette next to every ability on the sheet. Mapped, not fought: the severity names still come
   from the engine and this is still the only place they become colours.
*/
.badge.bg-secondary { background-color: var(--muted) !important; color: var(--on-accent) !important; }
.badge.bg-danger { background-color: var(--danger) !important; color: var(--on-accent) !important; }
.badge.bg-warning { background-color: var(--warn) !important; color: var(--on-accent) !important; }
.badge.bg-info { background-color: var(--accent-2) !important; color: var(--on-accent) !important; }

/*
   Bootstrap sets <code> to a pink of its own. The sheet uses it for the name of a derived value, which
   is a label rather than a snippet — but the colour was the part that came from somewhere else.
*/
code { color: var(--accent); }
.tag { display: inline-block; font-family: var(--font-ui); background: var(--bg); border: 1px solid var(--border); border-radius: 999px; padding: .1rem .55rem; font-size: .72rem; color: var(--muted); margin: .1rem .15rem .1rem 0; }
.tag.ok { border-color: var(--ok); color: var(--ok); }
.tag.danger { border-color: var(--danger); color: var(--danger); }

/* tables — Bootstrap's defaults assume a light background, so they are overridden rather than fought */
.table { --bs-table-color: var(--text); --bs-table-bg: transparent; --bs-table-border-color: var(--border); color: var(--text); font-size: .92rem; }
.table > thead th { font-family: var(--font-ui); text-align: left; font-size: .72rem; text-transform: uppercase; letter-spacing: .08em; color: var(--muted); border-bottom: 1px solid var(--border); }
.table > tbody td { border-bottom: 1px solid var(--border); vertical-align: middle; }
.table-striped > tbody > tr:nth-of-type(odd) > * { --bs-table-accent-bg: rgba(255, 255, 255, .02); color: var(--text); }
.table-warning, .table-warning > * { --bs-table-accent-bg: rgba(224, 179, 65, .12); color: var(--text); }
.table > :not(caption) > * > * { background-color: transparent; }

/*
   Bootstrap's list group is white with near-black text, which is its own palette again. The builder puts
   every outstanding finding in one and the sheet puts every rule that stayed prose in one, so the two
   places a character tells you something about itself were a page from another product.
*/
.list-group-item { background-color: var(--panel); color: var(--text); border-color: var(--border); }

/* alerts */
.alert { border-radius: var(--radius); border: 1px solid var(--border); background: var(--panel); color: var(--text); }
.alert-info { border-color: var(--accent-2); background: rgba(139, 92, 246, .12); }
.alert-warning { border-color: var(--warn); background: rgba(224, 179, 65, .10); }
.alert-danger { border-color: var(--danger); background: rgba(214, 69, 69, .12); }
.alert-success { border-color: var(--ok); background: rgba(63, 174, 106, .12); }

/* landing — its own layout, with no sidebar */
.landing { display: flex; flex-direction: column; min-height: 100vh; }
.landing-content { flex: 1 0 auto; padding: 2rem 2rem 3rem; max-width: 1000px; margin: 0 auto; width: 100%; }
.landing-footer { border-top: 1px solid var(--border); padding: 1rem 2rem; max-width: 1000px; margin: 0 auto; width: 100%; }
.landing-footer a { color: var(--muted); }
.landing-footer a:hover { color: var(--accent); }

.masthead { display: flex; align-items: center; gap: 1rem; padding-top: 1rem; }
.masthead-logo { width: 96px; height: 96px; object-fit: contain; }
.masthead-title { font-size: 2.6rem; margin: 0; color: var(--accent); letter-spacing: .04em; }
@media (max-width: 600px) {
    .masthead-logo { width: 64px; height: 64px; }
    .masthead-title { font-size: 2rem; }
    .landing-content, .landing-footer { padding-left: 1rem; padding-right: 1rem; }
}

.hero { padding: 2rem 0; max-width: 800px; }
/* The masthead carries the h1, so the hero's own line is an h2 and is sized up to read as the headline. */
.hero h2 { font-size: 2.6rem; line-height: 1.1; }
.hero p.lead { color: var(--muted); font-size: 1.15rem; }
.feature { padding: 1.2rem; border: 1px solid var(--border); border-radius: var(--radius); background: var(--panel); }
.feature .ico { margin-bottom: .1rem; }
.feature h3 { margin: .4rem 0 .2rem; font-size: 1.05rem; }

/* legal documents rendered from markdown */
.legal { max-width: 70ch; }
.legal h1 { margin-bottom: .25rem; }
.legal h2 { margin-top: 2rem; }
.legal blockquote { border-left: 3px solid var(--warn); padding-left: 1rem; color: var(--muted); }
.legal table { width: 100%; border-collapse: collapse; margin: 1rem 0; }
.legal th, .legal td { text-align: left; padding: .45rem .5rem; border-bottom: 1px solid var(--border); vertical-align: top; }
.legal th { font-family: var(--font-ui); font-size: .72rem; text-transform: uppercase; letter-spacing: .08em; color: var(--muted); }
.legal code { color: var(--accent); }

.validation-message { color: var(--danger); font-size: .8rem; }
.valid.modified:not([type=checkbox]) { outline: 1px solid var(--ok); }
.invalid { outline: 1px solid var(--danger); }

#blazor-error-ui { color-scheme: light only; background: lightyellow; bottom: 0; box-shadow: 0 -1px 2px rgba(0,0,0,.2); box-sizing: border-box; display: none; left: 0; padding: .6rem 1.25rem .7rem 1.25rem; position: fixed; width: 100%; z-index: 1000; color: black; }
#blazor-error-ui .dismiss { cursor: pointer; position: absolute; right: .75rem; top: .5rem; }
.blazor-error-boundary { background: #b32121; padding: 1rem 1rem 1rem 3.7rem; color: white; }
.darker-border-checkbox.form-check-input { border-color: #929292; }
