/* ACE.Market stylesheet. One file, no framework, no build step.
   Dark warm ground, Cormorant headings, Lora body: the game's own inventory panel, on the web. */

:root {
    --ground: #191714;
    --panel: #1f1c18;
    --input: #262219;
    --modal: #1c1915;

    --appraisal-fill: #141210;
    --appraisal-border: #6b5a2e;

    --text: #efe9df;
    --text-2: #d9cdb8;
    --muted: #a89f92;
    --faint: #7d7569;

    --gold: #e1ad66;
    --gold-border: #b68235;
    --gold-tint: rgba(182, 130, 53, 0.07);
    --gold-tint-2: rgba(182, 130, 53, 0.1);
    --gold-tint-3: rgba(182, 130, 53, 0.16);

    --frame-light: #907854;
    /* The client's exact middle-band colour. Kept for reference; not used directly in the band
       rules below, because on real screens it sits too close in brightness to --frame-light and
       the two light lines merge into one at 1x/1.25x scaling. */
    --frame-dark: #67553b;
    /* A darkened ground colour, deliberately darker than --frame-dark, used as the band's actual
       middle line so the two light lines stay visually separate. */
    --frame-gap: #2b241c;
    --frame-corner: #96794e;
    --frame-corner-hi: #b2956a;
    --frame-corner-lo: #74634a;

    --spell: #b9dbe6;
    --spell-border: rgba(143, 199, 214, 0.35);

    --ok: #8fbf8a;
    --err: #d97a6a;
    --warn: #e1ad66;

    --hairline: rgba(239, 233, 223, 0.12);
    --rule: rgba(239, 233, 223, 0.08);
    --input-border: rgba(239, 233, 223, 0.14);

    --head: "Cormorant Garamond", Georgia, serif;
    --body: "Lora", Georgia, serif;
}

/* One keyframe in the whole sheet. */
@keyframes rise {
    from { opacity: 0; transform: translateY(-4px); }
    to { opacity: 1; transform: none; }
}

/* ---------------------------------------------------------------- base ---- */

* { box-sizing: border-box; }

html, body { height: 100%; }

body {
    margin: 0;
    background: var(--ground);
    color: var(--text);
    font-family: var(--body);
    font-size: 14px;
    line-height: 1.5;
    display: flex;
    flex-direction: column;
    min-height: 100vh;
}

a {
    color: var(--gold);
    text-underline-offset: 3px;
    text-decoration-color: rgba(225, 173, 102, 0.45);
}

a:hover { color: #f0c98c; text-decoration-color: #f0c98c; }

h1, h2, h3 { font-family: var(--head); font-weight: 600; margin: 0; }

input, select, button, textarea { font: inherit; color: inherit; }

input::placeholder { color: rgba(239, 233, 223, 0.38); }

select option { background: var(--input); color: var(--text); }

::selection { background: rgba(182, 130, 53, 0.35); }

:focus { outline: none; }

:focus-visible { outline: 2px solid var(--gold-border); outline-offset: 2px; }

input[type=number]::-webkit-inner-spin-button { opacity: 0.4; }

[hidden] { display: none !important; }

/* ------------------------------------------------------------- icon slot ---- */

/* Layered icons. The four layers stack in document order: plate, underlay, base, overlay, exactly as
   the game client composites them. These rules are structural and must survive any restyling. */
.icon {
    position: relative;
    display: inline-block;
    width: 40px;
    height: 40px;
    vertical-align: middle;
    border-radius: 3px;
    background: linear-gradient(158deg, #514a3f 0%, #3d382f 55%, #2f2b24 100%);
    border: 1px solid #211f1a;
    box-shadow: inset 1px 1px 0 rgba(255, 255, 255, 0.13), inset -1px -1px 0 rgba(0, 0, 0, 0.5);
}

.icon .icon-layer {
    position: absolute;
    inset: 3px;
    width: 32px;
    height: 32px;
    /* The pack exports 32x32 art. Without this, any scaling blurs it into mush. */
    image-rendering: pixelated;
}

/* The enchantment halo the client draws behind an enchanted item's icon. There is no halo texture
   in the pack, so this is a glow on the icon box rather than a fifth layer. It restates the two
   inset bevel shadows from .icon because box-shadow does not merge across rules; it must therefore
   stay AFTER .icon in this file, since both are single-class selectors and document order decides.
   The colour comes from UiEffectGlows.cs, one class per effect suffix. */
.icon-glow {
    box-shadow:
        inset 1px 1px 0 rgba(255, 255, 255, 0.13),
        inset -1px -1px 0 rgba(0, 0, 0, 0.5),
        0 0 6px 1px var(--icon-glow);
}

/* PLACEHOLDER COLOUR, matching UiEffectGlows.MagicalGlow. Awaiting an in-game sample. */
.icon-glow--magical { --icon-glow: rgba(127, 182, 255, 0.75); }

/* The detail header draws the same 32px art at a whole multiple, never a resized pack file.
   The modifier lives on a WRAPPER so _Icon.cshtml itself stays untouched. */
.icon-frame-lg .icon { width: 72px; height: 72px; border-radius: 4px; }
.icon-frame-lg .icon .icon-layer { inset: 3px; width: 64px; height: 64px; }

/* The class plate the client draws under every inventory icon. It is the BOTTOM-most layer
   (first in document order, so it stacks under underlay/base/overlay with no z-index needed).
   When the loaded pack has the plate texture it renders as art; otherwise these flat colours
   stand in. One variant per ItemTypePlates.cs fallback group. */
.icon-plate--weapon { background-color: #865548; }
.icon-plate--armor { background-color: #1F3554; }
.icon-plate--clothing { background-color: #196670; }
.icon-plate--jewelry { background-color: #542348; }
.icon-plate--food { background-color: #1D381D; }
.icon-plate--gem { background-color: #142941; }
.icon-plate--spell { background-color: #2D2D2D; }
.icon-plate--misc { background-color: #694631; }

/* A key with no file. Reads as an empty slot rather than guessing at art. */
.icon-missing, .icon-placeholder {
    display: inline-block;
    background: rgba(0, 0, 0, 0.28);
    border: 1px dashed rgba(255, 255, 255, 0.22);
}

.icon-missing { position: relative; inset: auto; width: 40px; height: 40px; }

.icon-frame-lg .icon-missing { width: 72px; height: 72px; }

/* --------------------------------------------------------- gold panel frame ---- */
/* The client's interface frame: a thin light/dark/light gold band around a panel,
   with a bevelled square sitting on the band at each corner. Square corners only -
   border-radius is forced to 0 on every framed element.

   The inner line is a real border (paints under any opaque child background, e.g.
   thead tr); the middle and outer lines are box-shadow rings, which sit outside the
   border box and so are never painted over by a child. An inset shadow was tried
   first and rejected: it paints INSIDE the box, so an opaque child like `thead tr`
   covers it and the top edge loses its band and corners.

   Corner geometry: the band is 3px wide (border 1px, gap 1px, outer line 1px) and
   runs from 2px outside the border box to 1px inside it. The corner strips are
   absolutely positioned, so their offsets are measured from the PADDING box, one
   pixel further in than the border edge: -4px there is -3px from the outer edge, and
   a 5px square lands on [-3px, +2px], one pixel past the band on each side. The first
   cut used 7px squares, which overhung 1px outward and 3px inward and read as
   off-centre. */

.filters,
.framed,
.detail-card,
.card,
.modal-panel {
    position: relative;
    border: 1px solid var(--frame-light);
    border-radius: 0;
    box-shadow: 0 0 0 1px var(--frame-gap), 0 0 0 2px var(--frame-light);
}

.modal-panel {
    box-shadow: 0 0 0 1px var(--frame-gap), 0 0 0 2px var(--frame-light), 0 24px 64px rgba(0, 0, 0, 0.6);
}

.filters::before, .filters::after,
.framed::before, .framed::after,
.detail-card::before, .detail-card::after,
.card::before, .card::after,
.modal-panel::before, .modal-panel::after {
    content: "";
    position: absolute;
    left: -4px;
    right: -4px;
    height: 5px;
    pointer-events: none;
    z-index: 1;
    background-repeat: no-repeat;
    background-size: 5px 5px;
    background-position:
        left top, left top, left top, left top, left top,
        right top, right top, right top, right top, right top;
    background-image:
        linear-gradient(to bottom, var(--frame-corner-hi) 0 1px, transparent 1px 5px),
        linear-gradient(to right, var(--frame-corner-hi) 0 1px, transparent 1px 5px),
        linear-gradient(to top, var(--frame-corner-lo) 0 1px, transparent 1px 5px),
        linear-gradient(to left, var(--frame-corner-lo) 0 1px, transparent 1px 5px),
        linear-gradient(var(--frame-corner), var(--frame-corner)),
        linear-gradient(to bottom, var(--frame-corner-hi) 0 1px, transparent 1px 5px),
        linear-gradient(to right, var(--frame-corner-hi) 0 1px, transparent 1px 5px),
        linear-gradient(to top, var(--frame-corner-lo) 0 1px, transparent 1px 5px),
        linear-gradient(to left, var(--frame-corner-lo) 0 1px, transparent 1px 5px),
        linear-gradient(var(--frame-corner), var(--frame-corner));
}

.filters::before, .framed::before, .detail-card::before, .card::before, .modal-panel::before { top: -4px; }
.filters::after, .framed::after, .detail-card::after, .card::after, .modal-panel::after { bottom: -4px; }

/* ----------------------------------------------------------------- frame ---- */

.site-header {
    position: sticky;
    top: 0;
    z-index: 20;
    background: rgba(25, 23, 20, 0.92);
    backdrop-filter: blur(8px);
    border-bottom: 1px solid var(--frame-gap);
    box-shadow: 0 1px 0 var(--frame-light), inset 0 -1px 0 var(--frame-light);
}

.site-header-inner {
    max-width: 1180px;
    margin: 0 auto;
    padding: 0 28px;
    height: 60px;
    display: flex;
    align-items: center;
    gap: 28px;
}

.site-brand {
    display: flex;
    align-items: center;
    gap: 12px;
    text-decoration: none;
    color: var(--text);
    margin-right: 8px;
}

.site-brand img { width: 30px; height: 30px; border-radius: 6px; display: block; }

.site-brand span { font-family: var(--head); font-weight: 600; font-size: 22px; letter-spacing: 0.01em; }

.site-nav { display: flex; align-items: center; gap: 22px; font-size: 14px; }

.site-nav a {
    text-decoration: none;
    color: var(--text-2);
    padding: 6px 0;
    border-bottom: 1px solid transparent;
}

.site-nav a:hover { color: var(--gold); }

.site-nav a.is-active { color: var(--gold); border-bottom-color: var(--gold); }

.site-account { margin-left: auto; display: flex; align-items: center; gap: 16px; }

.account-pill {
    display: flex;
    align-items: baseline;
    gap: 10px;
    text-decoration: none;
    color: var(--text);
    padding: 6px 12px;
    border: 1px solid var(--input-border);
    border-radius: 4px;
}

.account-pill:hover { border-color: var(--gold-border); color: var(--text); }

.account-pill .account-name { font-size: 13px; }

.account-pill .account-balance { font-size: 13px; color: var(--gold); font-variant-numeric: tabular-nums; }

.signout-form { margin: 0; }

main {
    flex: 1;
    width: 100%;
    max-width: 1180px;
    margin: 0 auto;
    padding: 36px 28px 80px;
}

.site-footer {
    border-top: 1px solid var(--frame-gap);
    box-shadow: 0 -1px 0 var(--frame-light), inset 0 1px 0 var(--frame-light);
    width: 100%;
}

.site-footer-inner {
    padding: 18px 28px;
    font-size: 12px;
    color: var(--faint);
    display: flex;
    justify-content: space-between;
    gap: 16px;
    flex-wrap: wrap;
    max-width: 1180px;
    margin: 0 auto;
    width: 100%;
    box-sizing: border-box;
}

.site-footer-inner a { color: var(--gold); text-decoration: none; }

.site-footer-inner a:hover { text-decoration: underline; }

/* ------------------------------------------------------------------ page ---- */

.page { display: flex; flex-direction: column; gap: 22px; }

/* A titled block inside a page: its heading, its control panel and its table travel together with a
   tighter gap than the 22px .page puts between whole sections. */
.page-section { display: flex; flex-direction: column; gap: 12px; }

.section-title { font-size: 22px; }

.page-title {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 20px;
    flex-wrap: wrap;
}

.page-title h1 { font-size: 40px; line-height: 1.05; }

.page-title .title-note { margin: 0; font-size: 13px; color: var(--muted); }

.page-title .title-note.tabular { font-variant-numeric: tabular-nums; }

.title-stack { display: flex; flex-direction: column; gap: 4px; }

.title-counts { display: flex; gap: 20px; font-size: 13px; color: var(--muted); font-variant-numeric: tabular-nums; }

.title-counts .count-total { color: var(--text); }

.title-counts .count-listed { color: var(--gold); }

.narrow-page { max-width: 420px; margin: 40px auto 0; display: flex; flex-direction: column; gap: 20px; }

.narrow-page-wide { max-width: 520px; }

/* --------------------------------------------------------------- buttons ---- */

.btn, .btn-primary, .btn-secondary, .btn-ghost {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    min-height: 36px;
    padding: 6px 14px;
    border-radius: 4px;
    background: transparent;
    cursor: pointer;
    text-decoration: none;
    white-space: nowrap;
}

.btn-primary {
    border: 1px solid var(--gold-border);
    color: var(--gold);
    font-family: var(--head);
    font-weight: 600;
    font-size: 15px;
}

.btn-primary:hover { background: var(--gold-tint-3); color: var(--gold); }

.btn-primary.is-armed { background: var(--gold-tint-3); }

.btn-lg { min-height: 40px; padding: 8px 16px; font-size: 17px; }

.btn-block { width: 100%; min-height: 42px; font-size: 17px; }

.btn-secondary {
    border: 1px solid var(--input-border);
    color: var(--text);
    font-size: 13px;
}

.btn-secondary:hover { border-color: rgba(239, 233, 223, 0.4); color: var(--text); }

.btn-ghost {
    border: 1px solid transparent;
    color: var(--gold);
    font-size: 13px;
}

.btn-ghost:hover { background: var(--gold-tint-2); color: var(--gold); }

.btn-destructive { border-color: rgba(239, 233, 223, 0.2); color: var(--text-2); }

.btn-destructive:hover { border-color: var(--err); color: var(--err); }

.btn-small { min-height: 30px; padding: 5px 12px; font-size: 13px; }

/* 33px, half again over the 22px it was: the barrel is a whole action of its own and had to be
   hunted for at the old size. Kept in step with .btn-bulk-barrel img further down, which is the
   same art in the toolbar. */
.btn-barrel { background: none; border: 1px solid transparent; padding: 0.15rem 0.3rem; line-height: 1; cursor: pointer; }
.btn-barrel img { width: 33px; height: 33px; display: block; }
.btn-barrel:hover { border-color: var(--err); }

/* --------------------------------------------------------- confirm step ---- */

/* Bordered in the error colour without being an error: it is the one panel that must not be
   skimmed past, because the click after it cannot be taken back by the player. */
.confirm-action { border: 1px solid var(--err); border-radius: 3px; padding: 1rem; margin: 1rem 0; }

.confirm-title { margin: 0 0 0.5rem; font-size: 1.1rem; }

.confirm-body { margin: 0 0 0.75rem; color: var(--text-2); }

.confirm-items { margin: 0 0 0.75rem 1.25rem; }

.confirm-actions { display: flex; gap: 0.5rem; align-items: center; }

/* ---------------------------------------------------------------- fields ---- */

.field { display: flex; flex-direction: column; gap: 5px; min-width: 0; }

.field-label-row { display: flex; align-items: center; gap: 6px; }

.field > label, .field > .field-label, fieldset.range > legend {
    font-size: 12px;
    color: var(--muted);
    padding: 0;
}

.field-hint { color: var(--faint); }

.text-input, .number-input, select.select-input {
    width: 100%;
    min-height: 36px;
    padding: 6px 10px;
    background: var(--input);
    border: 1px solid var(--input-border);
    border-radius: 4px;
    color: var(--text);
    caret-color: var(--gold-border);
}

.number-input { font-variant-numeric: tabular-nums; }

.text-input:hover, .number-input:hover, select.select-input:hover { border-color: rgba(239, 233, 223, 0.4); }

.text-input:focus, .number-input:focus, select.select-input:focus { border-color: var(--gold-border); }

.input-tall { min-height: 40px; padding: 8px 12px; }

fieldset.range {
    border: 0;
    padding: 0;
    margin: 0;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 5px;
}

fieldset.range > legend { margin-bottom: 5px; }

.range-pair { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; }

/* ---------------------------------------------------------- filter panel ---- */

.filters {
    display: flex;
    flex-direction: column;
    gap: 12px;
    padding: 16px;
    background: var(--panel);
    margin: 0;
}

.filter-row {
    display: flex;
    flex-wrap: wrap;
    gap: 12px;
    align-items: end;
}

/* The flex BASIS is what decides where the row wraps; the grow factors are what decide how it
   looks once it has not. Keeping the grow factors and pulling the bases in therefore changes
   nothing at desktop width - the fields still expand to fill the row in the same proportions -
   and only moves the point at which the actions group drops to a second line. Measured by
   rendering both filter rows at 1440/1280/1024/960/900/820: the vault row now holds one line down
   to roughly 840px, where it held to about 940px before. Below that the segmented Show control and
   the actions group are fixed-width floors and the row has to wrap. */
.filter-row .grow-text { flex: 1.6 1 180px; position: relative; }
.filter-row .grow-type { flex: 1 1 120px; }
.filter-row .grow-price { flex: 1.3 1 170px; }
.filter-row .grow-vault-text { flex: 2 1 180px; }

.filter-actions { display: flex; gap: 6px; align-items: center; min-height: 36px; flex: 0 0 auto; margin-left: auto; }

.filter-more {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    gap: 12px;
    padding-top: 12px;
    border-top: 1px solid rgba(239, 233, 223, 0.1);
    animation: rise 140ms ease-out;
}

/* The segmented Show control: three real submit buttons in one bordered group. */
.segmented {
    display: inline-flex;
    border: 1px solid var(--input-border);
    border-radius: 4px;
    overflow: hidden;
    min-height: 36px;
}

.segmented button {
    padding: 6px 14px;
    background: transparent;
    border: 0;
    color: var(--text-2);
    cursor: pointer;
    font-size: 13px;
}

.segmented button + button { border-left: 1px solid var(--input-border); }

.segmented button:hover { background: rgba(239, 233, 223, 0.06); }

.segmented button[aria-pressed="true"] { color: var(--gold); box-shadow: inset 0 0 0 1px var(--gold-border); }

/* ------------------------------------------------------------- type-ahead ---- */

.listbox {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    margin: 4px 0 0;
    padding: 4px;
    list-style: none;
    background: var(--input);
    border: 1px solid rgba(239, 233, 223, 0.16);
    border-radius: 4px;
    box-shadow: 0 12px 32px rgba(0, 0, 0, 0.5);
    z-index: 10;
    max-height: 280px;
    overflow-y: auto;
    animation: rise 120ms ease-out;
}

.listbox li {
    display: flex;
    justify-content: space-between;
    gap: 12px;
    padding: 7px 10px;
    border-radius: 3px;
    cursor: pointer;
    font-size: 13px;
}

.listbox li:hover, .listbox li.is-active { background: rgba(182, 130, 53, 0.14); }

.listbox .option-kind { color: var(--muted); font-size: 11px; letter-spacing: 0.06em; text-transform: uppercase; }

.listbox .option-count { color: var(--muted); font-size: 12px; font-variant-numeric: tabular-nums; }

/* ------------------------------------------------------------ search help ---- */

.info-icon {
    flex: none;
    width: 16px;
    height: 16px;
    padding: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    border: 1px solid var(--muted);
    background: transparent;
    color: var(--muted);
    font-size: 10px;
    font-style: italic;
    cursor: pointer;
}

.info-icon:hover { border-color: var(--gold-border); color: var(--gold); }

/* Same round icon-button treatment as .info-icon, just sized for a page title rather than a
   filter-field label, and holding an SVG glyph instead of a lone letter. */
.share-icon {
    flex: none;
    width: 28px;
    height: 28px;
    padding: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    border: 1px solid var(--muted);
    background: transparent;
    color: var(--muted);
    cursor: pointer;
}
.share-icon:hover { border-color: var(--gold-border); color: var(--gold); }
.share-icon.is-copied { border-color: var(--gold-border); color: var(--gold); }

/* Positioned wrapper the share icon now lives in (in the header, left of the account pill), so the
   copied-link chip below can sit at position: absolute without disturbing the row it's in. */
.share-icon-wrap { position: relative; display: flex; align-items: center; flex: none; }

/* The visible "copied" confirmation - out of flow so it never pushes the account pill or Sign out
   button sideways when it appears or fades. Anchored under the icon; .site-header/-inner carry no
   overflow rule, so it is never clipped by the header even though the icon sits close to its edge. */
.share-copied-chip {
    position: absolute;
    top: 100%;
    left: 50%;
    transform: translateX(-50%);
    margin-top: 8px;
    padding: 4px 8px;
    border-radius: 4px;
    background: var(--gold);
    color: var(--ground);
    font-size: 12px;
    font-weight: 600;
    white-space: nowrap;
    pointer-events: none;
    opacity: 0;
    transition: opacity 160ms ease;
    z-index: 5;
}

.share-copied-chip.is-visible { opacity: 1; }

/* The manual-copy fallback input market.js inserts next to .share-icon. Same out-of-flow treatment
   as .share-copied-chip and for the same reason: an in-flow fixed-width input dropped into this
   nowrap header row would push the account pill and Sign out button sideways instead of just
   overlaying. right: 0 (rather than the chip's centered left: 50%) keeps it from running past the
   header's right edge, since the icon sits close to the end of the row. Free to be wider than the
   old in-flow 170px now that it overlays instead of widening the row. */
.share-fallback {
    position: absolute;
    top: 100%;
    right: 0;
    margin-top: 8px;
    width: 260px;
    z-index: 5;
}

.info-popover {
    max-width: 320px;
    padding: 10px 12px;
    background: var(--input);
    border: 1px solid rgba(239, 233, 223, 0.16);
    border-radius: 4px;
    box-shadow: 0 12px 32px rgba(0, 0, 0, 0.5);
    color: var(--text-2);
    font-size: 12px;
    line-height: 1.5;
}

.info-popover p + p { margin-top: 6px; }

.info-popover code {
    color: var(--gold);
    font-size: 11px;
}

/* ------------------------------------------------------------ count line ---- */

.result-line {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 16px;
    font-size: 13px;
    color: var(--muted);
    margin: 0;
}

.result-count { font-variant-numeric: tabular-nums; }

/* ---------------------------------------------------------------- tables ---- */

.table-scroll {
    overflow-x: auto;
}

table.listings, table.vault, table.history {
    width: 100%;
    border-collapse: collapse;
    font-size: 13.5px;
}

table.listings { min-width: 820px; }
table.vault { min-width: 930px; }
table.history { min-width: 820px; }

table.my-listings { min-width: 640px; }

thead tr { background: var(--panel); }

th {
    text-align: left;
    padding: 10px 12px;
    font-size: 11px;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--muted);
    font-weight: 500;
    border-bottom: 1px solid rgba(239, 233, 223, 0.14);
}

th.col-icon { width: 56px; }
th.col-num { width: 32px; text-align: right; }
/* Wide enough for the List button and the 33px barrel to sit side by side without wrapping. */
th.col-action { width: 150px; text-align: right; }
th.num { text-align: right; }

/* A sortable header is a real link, so it works with JavaScript off. It fills the cell. */
th.sortable { padding: 0; }

th.sortable a {
    display: block;
    width: 100%;
    padding: 10px 12px;
    text-decoration: none;
    color: var(--muted);
    font-size: 11px;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    font-weight: 500;
}

th.sortable.num a { text-align: right; }

th.sortable a:hover { color: var(--gold); }

th.sortable[aria-sort] a { color: var(--gold); }

tbody tr { border-bottom: 1px solid var(--rule); }

td { padding: 6px 12px; }

td.num { text-align: right; font-variant-numeric: tabular-nums; color: var(--text-2); }

/* The Dmg column is a composite string ("+163% +5 (Fire)"), not a number, so it reads left-aligned
   and must not wrap mid-value. Its header keeps th.num's right alignment off for the same reason. */
td.dmg { text-align: left; white-space: nowrap; color: var(--text-2); }

th.dmg { text-align: left; }

th.sortable.dmg a { text-align: left; }

td.text { color: var(--text-2); }

td.entry-number { text-align: right; font-variant-numeric: tabular-nums; color: var(--faint); font-size: 12px; }

td.price { text-align: right; font-variant-numeric: tabular-nums; color: var(--gold); font-weight: 500; }

tr.row-link { cursor: pointer; }

tr.row-link:hover, tbody tr:hover { background: var(--gold-tint); }

.row-name { text-decoration: none; color: var(--text); font-weight: 500; }

.row-name:hover { color: var(--gold); }

.row-sub { font-size: 12px; color: var(--muted); }

td.listed-yes { font-variant-numeric: tabular-nums; color: var(--gold); }

td.listed-no { color: var(--faint); }

/* --------------------------------------------------------- empty states ---- */

.empty-state {
    padding: 48px 24px;
    text-align: center;
    display: flex;
    flex-direction: column;
    gap: 8px;
    align-items: center;
}

.empty-state .empty-title { font-family: var(--head); font-size: 24px; font-weight: 500; }

.empty-state p { margin: 0; color: var(--muted); max-width: 46ch; }

.empty-state .btn-primary, .empty-state a.btn-primary { margin-top: 8px; }

/* -------------------------------------------------------------- messages ---- */

.error, .success, .warning {
    display: flex;
    gap: 12px;
    align-items: flex-start;
    padding: 12px 14px;
    border: 1px solid var(--hairline);
    border-left: 3px solid var(--muted);
    border-radius: 4px;
    font-size: 13px;
    color: var(--text-2);
    background: var(--panel);
    margin: 0;
    animation: rise 160ms ease-out;
}

.error { border-left-color: var(--err); }
.success { border-left-color: var(--ok); }
.warning { border-left-color: var(--warn); }

.msg-glyph {
    flex: none;
    width: 18px;
    height: 18px;
    border-radius: 50%;
    border: 1px solid var(--muted);
    font-size: 11px;
    display: grid;
    place-items: center;
    font-weight: 600;
}

.error .msg-glyph { border-color: var(--err); color: var(--err); }
.success .msg-glyph { border-color: var(--ok); color: var(--ok); }
.warning .msg-glyph { border-color: var(--warn); color: var(--warn); }

.msg-text { flex: 1; }

.msg-dismiss {
    background: transparent;
    border: 0;
    color: var(--muted);
    cursor: pointer;
    font-size: 14px;
    line-height: 1;
    padding: 0 2px;
}

.msg-dismiss:hover { color: var(--text); }

/* The ambient warning: a dashed gold strip under the title, no fill. */
.warning-ambient {
    background: transparent;
    border: 1px dashed rgba(225, 173, 102, 0.5);
    border-left: 1px dashed rgba(225, 173, 102, 0.5);
    padding: 10px 14px;
}

/* ----------------------------------------------------------- item detail ---- */

.detail-page { display: flex; flex-direction: column; gap: 20px; }

.detail-head {
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 16px;
}

.detail-kicker { font-size: 12px; color: var(--muted); letter-spacing: 0.08em; text-transform: uppercase; }

.detail-back { font-size: 13px; text-decoration: none; }

.detail-close {
    width: 34px;
    height: 34px;
    display: grid;
    place-items: center;
    background: transparent;
    border: 1px solid rgba(239, 233, 223, 0.16);
    border-radius: 4px;
    color: var(--muted);
    cursor: pointer;
    font-size: 18px;
    line-height: 1;
}

.detail-close:hover { border-color: var(--gold-border); color: var(--text); }

.item-detail { display: flex; flex-wrap: wrap; gap: 32px; align-items: start; }

.detail-main { display: flex; flex-direction: column; gap: 24px; min-width: 0; flex: 1 1 460px; }

.detail-main > header { display: flex; align-items: center; gap: 20px; }

.detail-heading { display: flex; flex-direction: column; gap: 4px; min-width: 0; }

.detail-heading h1 { font-size: 36px; line-height: 1.05; }

.detail-sub { font-size: 13px; color: var(--muted); }

.item-desc { margin: 0; font-style: italic; color: var(--text-2); max-width: 60ch; }

/* The one deliberately game-native element: the client's own appraisal panel. */
.appraisal {
    border: 1px solid var(--appraisal-border);
    border-radius: 4px;
    background: var(--appraisal-fill);
    box-shadow: inset 0 0 0 1px rgba(182, 130, 53, 0.18), 0 8px 24px rgba(0, 0, 0, 0.4);
    overflow: hidden;
}

.appraisal-bar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 8px 14px;
    background: linear-gradient(180deg, #2a2419, #1d1913);
    border-bottom: 1px solid var(--appraisal-border);
}

.appraisal-bar .appraisal-title { font-family: var(--head); font-weight: 600; font-size: 16px; color: var(--gold); letter-spacing: 0.02em; }

.appraisal-bar .appraisal-asof { font-size: 11px; color: var(--muted); letter-spacing: 0.06em; text-transform: uppercase; }

ul.panel-lines {
    margin: 0;
    padding: 14px 16px;
    list-style: none;
    columns: 2;
    column-gap: 28px;
    font-size: 13px;
    line-height: 1.7;
    color: var(--text-2);
    font-variant-numeric: tabular-nums;
}

ul.panel-lines li { break-inside: avoid; }

.appraisal-spells { padding: 12px 16px 16px; border-top: 1px dashed rgba(107, 90, 46, 0.6); }

.spells-heading { margin: 0 0 8px; font-family: var(--head); font-weight: 600; font-size: 16px; color: var(--gold); }

ul.spells { margin: 0; padding: 0; list-style: none; display: flex; flex-wrap: wrap; gap: 6px 8px; }

ul.spells li {
    font-size: 12.5px;
    padding: 3px 9px;
    border: 1px solid var(--spell-border);
    border-radius: 3px;
    color: var(--spell);
}

.detail-aside { display: flex; flex-direction: column; gap: 16px; flex: 0 1 320px; min-width: 280px; }

.detail-card {
    background: var(--panel);
    padding: 18px;
    display: flex;
    flex-direction: column;
    gap: 14px;
}

dl.item-facts {
    margin: 0;
    display: grid;
    grid-template-columns: max-content 1fr;
    gap: 8px 18px;
    font-size: 13.5px;
}

dl.item-facts dt { color: var(--muted); }

dl.item-facts dd { margin: 0; color: var(--text-2); font-variant-numeric: tabular-nums; }

dl.item-facts dd.fact-gold { color: var(--gold); font-weight: 500; }

dl.item-facts dd.fact-muted { color: var(--muted); }

.detail-action {
    display: flex;
    flex-direction: column;
    gap: 12px;
    padding-top: 14px;
    border-top: 1px solid rgba(239, 233, 223, 0.1);
    margin: 0;
}

.detail-note {
    margin: 0;
    padding-top: 14px;
    border-top: 1px solid rgba(239, 233, 223, 0.1);
    font-size: 13px;
    color: var(--muted);
}

.buy-line {
    display: flex;
    justify-content: space-between;
    gap: 12px;
    font-size: 13px;
    color: var(--muted);
    font-variant-numeric: tabular-nums;
}

.buy-line .buy-value { color: var(--text); }

.buy-line .buy-value.is-negative { color: var(--err); }

.field-row { display: grid; grid-template-columns: auto 1fr; gap: 12px; align-items: center; }

.field-row label { font-size: 13px; color: var(--muted); }

.signin-note { margin: 0; font-size: 12px; color: var(--muted); text-align: center; }

.recent-sales { margin: 0; font-size: 12.5px; color: var(--muted); line-height: 1.5; max-width: 46ch; }

.recent-sales .recent-label { color: var(--gold); }

.recent-sales.is-none { color: var(--faint); }

.gone-state {
    padding: 56px 24px;
    text-align: center;
    border: 1px solid var(--hairline);
    border-radius: 6px;
    display: flex;
    flex-direction: column;
    gap: 8px;
    align-items: center;
}

.gone-state .gone-title { font-family: var(--head); font-size: 28px; font-weight: 500; }

.gone-state p { margin: 0; color: var(--muted); max-width: 44ch; }

.gone-state a { margin-top: 8px; }

/* ----------------------------------------------------------------- modal ---- */

.modal-backdrop {
    position: fixed;
    inset: 0;
    z-index: 40;
    background: rgba(12, 10, 8, 0.72);
    backdrop-filter: blur(3px);
    display: grid;
    place-items: start center;
    padding: 56px 20px 40px;
    overflow-y: auto;
    animation: rise 140ms ease-out;
}

.modal-panel {
    width: min(1040px, 100%);
    background: var(--modal);
    padding: 28px 28px 32px;
}

body.modal-open { overflow: hidden; }

/* ------------------------------------------------------------- login card ---- */

.card {
    display: flex;
    flex-direction: column;
    gap: 14px;
    padding: 22px;
    background: var(--panel);
    margin: 0;
}

.card .btn-block { margin-top: 6px; }

.form-note { margin: 0; font-size: 13px; color: var(--muted); }

/* ------------------------------------------------------------- character ---- */

.character-list { margin: 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: 8px; }

.character-list button {
    width: 100%;
    display: flex;
    justify-content: space-between;
    align-items: center;
    gap: 16px;
    padding: 14px 18px;
    background: var(--panel);
    border: 1px solid var(--hairline);
    border-radius: 6px;
    color: var(--text);
    cursor: pointer;
    text-align: left;
}

.character-list button:hover { border-color: var(--gold-border); background: rgba(182, 130, 53, 0.08); }

.character-name { font-family: var(--head); font-weight: 600; font-size: 20px; }

.character-balance { font-variant-numeric: tabular-nums; color: var(--gold); font-size: 15px; }

/* ------------------------------------------------------------ vault rows ---- */

.vault-list-form {
    display: flex;
    flex-direction: column;
    gap: 8px;
    align-items: stretch;
    margin: 0;
}

/* Once JS moves the form into its own full-width row it lays out horizontally. */
tr.vault-list-row { background: var(--gold-tint); }

tr.vault-list-row > td { padding: 12px 12px 14px 80px; }

tr.vault-list-row .vault-list-form {
    flex-direction: row;
    align-items: end;
    flex-wrap: wrap;
    gap: 14px;
    animation: rise 140ms ease-out;
}

tr.vault-list-row .vault-list-form .field { flex: 0 0 auto; }

tr.vault-list-form-qty { width: 110px; }

tr.vault-list-row .recent-sales { margin: 0 0 8px auto; }

.vault-list-form .number-input { max-width: 130px; }

.vault-delist-form { margin: 0; display: flex; justify-content: flex-end; }

td.vault-action { text-align: right; white-space: nowrap; }

/* A form is a block element, so the barrel used to start its own line under the List button and
   made the row taller than every one beside it. Inline-block puts the two controls on the one
   line that the cell's text-align already right-justifies. The list form deliberately stays a
   block: with JavaScript it is lifted into its own full-width row, and without it, it belongs
   under the buttons rather than beside them. */
.vault-barrel-form { display: inline-block; margin: 0; vertical-align: middle; }
td.vault-action .list-toggle { vertical-align: middle; }

.list-toggle.is-open { background: var(--gold-tint-3); }

/* ----------------------------------------------------------- history tags ---- */

table.history td { padding: 9px 12px; }

td.history-when { font-variant-numeric: tabular-nums; color: var(--muted); white-space: nowrap; }

td.history-item { color: var(--text); }

td.history-side-bought { color: var(--text-2); }

td.history-side-sold { color: var(--gold); }

td.history-total { text-align: right; font-variant-numeric: tabular-nums; font-weight: 500; }

td.history-total.is-buy { color: var(--text-2); }

td.history-total.is-sell { color: var(--ok); }

.status-tag {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    font-size: 12px;
    padding: 2px 9px;
    border: 1px solid rgba(239, 233, 223, 0.2);
    border-radius: 3px;
    color: var(--text-2);
    text-transform: capitalize;
}

.status-tag.status-pending { border-color: var(--gold); color: var(--gold); }
.status-tag.status-refunded { border-color: rgba(143, 199, 214, 0.4); color: var(--spell); }
.status-tag.status-failed { border-color: var(--err); color: var(--err); }

.status-note { font-size: 11.5px; color: var(--muted); margin-top: 3px; }

/* --------------------------------------------------------------- toasts ---- */

/* Bottom right, out of the way of the header pill and the table. The container itself never
   catches a click, so an empty stack cannot swallow the page underneath it. */
/* Top centre, clear of the 60px sticky header, stacking downward. The header is where the balance
   this news is about already lives, so the eye has one place to look. */
#toasts {
    position: fixed;
    top: 72px;
    left: 50%;
    transform: translateX(-50%);
    z-index: 60;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    pointer-events: none;
}

.toast {
    pointer-events: auto;
    display: flex;
    gap: 12px;
    align-items: flex-start;
    max-width: 340px;
    padding: 11px 13px;
    background: var(--panel);
    border: 1px solid var(--hairline);
    border-left: 3px solid var(--muted);
    border-radius: 4px;
    font-family: var(--body);
    font-size: 13px;
    color: var(--text-2);
    box-shadow: 0 12px 32px rgba(0, 0, 0, 0.5);
    animation: rise 160ms ease-out;
}

/* Cyan for money coming in, gold for money going out: the same two colours the History
   table already spends and earns in. */
.toast-sold { border-left-color: var(--spell); }
.toast-bought { border-left-color: var(--gold); }

.toast-text { flex: 1; }

.toast-dismiss {
    background: transparent;
    border: 0;
    color: var(--muted);
    cursor: pointer;
    font-size: 14px;
    line-height: 1;
    padding: 0 2px;
}

.toast-dismiss:hover { color: var(--text); }

/* -------------------------------------------------------- vault loading ---- */

.vault-loading {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 14px;
    padding: 48px 24px;
    text-align: center;
}

.vault-spinner {
    width: 28px;
    height: 28px;
    border-radius: 50%;
    border: 2px solid rgba(182, 130, 53, 0.25);
    border-top-color: var(--gold);
    animation: spin 900ms linear infinite;
}

@keyframes spin { to { transform: rotate(360deg); } }

/* A ring that does not turn still reads as "not finished yet", which is the whole message. */
@media (prefers-reduced-motion: reduce) {
    .vault-spinner { animation: none; }
}

.vault-loading-text { color: var(--muted); margin: 0; }

/* The same waiting state, but inline where a write's answer would have gone: a panel rather than a
   full-height block, because the page around it is still the page the player was using. */
.write-retry {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 10px;
    padding: 16px 14px;
    background: var(--panel);
    border: 1px solid var(--hairline);
    border-left: 3px solid var(--gold);
    border-radius: 4px;
    text-align: center;
    animation: rise 160ms ease-out;
}

.write-retry .vault-spinner { width: 22px; height: 22px; }

.write-retry .retry-form { margin: 0; }

/* -------------------------------------------------- progressive enhancement ---- */

/* Anything marked js-only stays hidden until market.js claims the page. */
html:not(.js) .js-only { display: none !important; }

/* The no-JS submit button: live filtering makes it redundant, so JS hides it. */
html.js .no-js-only { display: none !important; }

/* -------------------------------------------------- bulk vault actions -------- */

.bulk-actions { margin: 0 0 0.5rem; }

.bulk-fieldset {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    align-items: flex-end;
    border: 1px solid var(--input-border);
    border-radius: 4px;
    padding: 0.5rem 0.75rem 0.6rem;
    margin: 0;
}

.bulk-fieldset legend {
    padding: 0 0.35rem;
    color: var(--text-2);
    font-size: 12px;
    letter-spacing: 0.04em;
    text-transform: uppercase;
}

/* Progressive enhancement, and it has to be keyed on html.js rather than on the panel alone:
   .js is added by market.js itself, so with JavaScript off - or if the script fails to load -
   the bulk fields are simply visible from the start and the whole flow still works. With
   JavaScript they appear as soon as a row is ticked. */
html.js .bulk-actions .bulk-fieldset { display: none; }
html.js .bulk-actions.is-armed .bulk-fieldset { display: flex; }

/* The select-all lives in the table's own header cell, so the column stays narrow and the
   count sits right beside the box. */
.col-select { width: 2.6rem; text-align: center; }
.bulk-all { display: inline-flex; align-items: center; gap: 0.25rem; cursor: pointer; }
.bulk-all-count { color: var(--text-2); font-size: 11px; font-weight: 400; }
.visually-hidden { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }

/* Same look as the per-row .btn-barrel, kept as its own selector: see the doc comment on the
   toolbar button in Vault.cshtml for why it cannot share the class name. */
.btn-bulk-barrel { background: none; border: 1px solid transparent; padding: 0.15rem 0.3rem; line-height: 1; cursor: pointer; }
.btn-bulk-barrel img { width: 33px; height: 33px; display: block; }
.btn-bulk-barrel:hover { border-color: var(--err); }

/* -------------------------------------------------- wanted board -------------- */

.wanted .inline-form { display: flex; gap: 0.5rem; align-items: center; }
.wanted .number-input { width: 4.5rem; }
