/* ==========================================================================
   Office Mafia theme
   --------------------------------------------------------------------------
   Sits on top of Bootstrap 3.1.1, which the templates depend on for grid and
   component classes. This file overrides its look without changing markup.

   Layout contract inherited from the stock theme -- do not change these
   without checking js/mobile.js:
     .side-bar        220px, floated left
     .game-container  the rest, floated right
     .show-sidebar    mobile toggle: swaps sidebar and content visibility

   Everything visual is driven by the custom properties below. Retuning the
   palette should not require touching a single rule.
   ========================================================================== */

:root {
    /* Mafiaens Hevn's own palette, read off its stylesheet
       (mafiaenshevn.com/css/main_new.css) rather than eyeballed from a
       screenshot -- these are its literal values and roles.
       Note MH's panels are neutral dark grey, NOT blue: the blue lives only in
       the borders, headings and buttons. Tinting the panels is what made this
       theme read as "blue-grey" instead of like MH. */
    --bg:          #000000;   /* MH: body base behind the city photo */
    --surface:     #1e1e1e;   /* MH: .bigbox / .rightbox / .mediumbox */
    --surface-2:   #161616;   /* MH: h1.title, inputs */
    --surface-3:   #181818;   /* MH: blockquote */
    --border:      #04354a;   /* MH: box borders, title underline */
    --border-soft: #05333c;   /* MH: input and radio borders */

    --text:        #cccccc;   /* MH: links, .title, footer */
    --text-dim:    #a8a8a8;   /* MH: .box-content, .infobox p */
    --muted:       #818181;   /* MH: body */

    --accent:      #3e6d97;   /* MH: h2, h3, h4 */
    --accent-hover:#2291ac;   /* MH: the glow on its big submit buttons */
    --accent-weak: rgba(62, 109, 151, 0.15);

    /* MH's submit buttons: a vertical gradient with a lit teal rim. */
    --btn-from:    #0a3348;
    --btn-to:      #0f3e59;
    --btn-border:  #085670;
    --btn-text:    #e0e0e0;
    --btn-glow:    #2291ac;

    /* MH's alert boxes: flat fill, dashed border, plain --text label. */
    --ok-bg:       #2b3c2b;  --ok-border:   #4f614f;
    --bad-bg:      #4d1f1f;  --bad-border:  #7c3a3a;
    --info-bg:     #163144;  --info-border: #3b586f;

    /* Kept saturated deliberately: these drive health bars and labels, which
       MH renders as plain text and so gives no colour to copy. */
    --success:     #3ecf8e;
    --danger:      #f2655c;
    --warning:     #eab308;

    --radius:      10px;
    --radius-sm:   6px;

    --s1: 4px;
    --s2: 8px;
    --s3: 12px;
    --s4: 16px;
    --s5: 24px;

    --font: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
    --shadow: 0 1px 2px rgba(0, 0, 0, 0.28);
}

/* No light mode: Mafiaens Hevn is dark-only, and a light variant reintroduced
   the blue-grey look this theme was pulled away from. The palette above is the
   single source of truth in every OS theme. */

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

html, body {
    background-color: var(--bg);
    color: var(--text);
    font-family: var(--font);
    font-size: 14px;
    line-height: 1.5;
    -webkit-font-smoothing: antialiased;
}

/* The page background.
   It lives on a fixed pseudo-element rather than on body itself because
   filter: blur() applied to body would blur every child element along with it.
   body must stay transparent for the layer to show: a background-colour here
   would paint over a z-index -1 child. --bg on html is the colour underneath,
   visible while the image loads and if it ever 404s. */
body {
    padding-bottom: var(--s5);
    background-color: transparent;
}

body::before {
    content: "";
    position: fixed;
    inset: 0;
    z-index: -1;
    /* -web.jpg is main-background.png downscaled to 1280px and JPEG-encoded:
       114 KB against the original's 5.4 MB, which took ~160s over the tunnel.
       The blur below discards the detail the extra pixels would have bought,
       so the two are indistinguishable on screen. The 2400x1600 original is
       kept beside it as the source to re-cut from. */
    background-image: url("../images/main-background-web.jpg");
    background-position: center center;
    background-repeat: no-repeat;
    background-size: cover;
    /* Dimmed so panel text keeps its contrast, softened so the image reads as
       atmosphere instead of detail competing with the UI. */
    filter: blur(5px) brightness(0.55);
    /* blur() samples beyond the element's edges and leaves a translucent rim.
       Scaling up pushes that rim outside the viewport. */
    transform: scale(1.08);
}

/* No image may push the page wider than the viewport. The logo is 377px
   intrinsic, which overflows a 375px phone unless width is constrained too --
   max-height alone does not do it. */
img { height: auto; max-width: 100%; }

/* A finished countdown reads "Klar" and picks up the accent colour, so a ready
   action stands out from the dim grey of one still counting down -- the same
   cue Mafiaens Hevn gives. timer.js maintains these two classes. */
.timer-done   { color: var(--accent); font-weight: 600; }
.timer-active { color: var(--muted); }

/* Underline "Klar" only while the cursor is on the word itself, not anywhere on
   the row -- the whole row is already a link, so underlining from a hover 20px
   away read as the label reacting to the wrong thing. Keyboard focus still
   underlines from the row, since focus has no pointer position to track. */
.timer-done:hover,
a.list-group-item:focus .timer-done { text-decoration: underline; }

a { color: var(--accent); text-decoration: none; }
a:hover, a:focus { color: var(--accent-hover); text-decoration: none; }

h1, h2, h3, h4, h5 { color: var(--text); font-weight: 600; letter-spacing: -0.01em; }

hr { border-color: var(--border-soft); }

small { color: var(--text-dim); }

/* Money, timers and counters must not make columns jitter as they tick. */
.side-bar small,
.crime-holder .cooldown,
[data-ajax-element],
[data-timer] {
    font-variant-numeric: tabular-nums;
    font-feature-settings: "tnum";
}

/* ---------- topbar ---------- */

.topbar {
    background-color: var(--surface);
    border-bottom: 1px solid var(--border);
    margin-bottom: var(--s4);
}

.topbar-inner {
    align-items: center;
    display: flex;
    gap: var(--s4);
    margin: 0 auto;
    max-width: 1500px;
    padding: var(--s2) var(--s4);
}

.topbar-logo { flex: 0 0 auto; line-height: 0; }
.topbar-logo img { max-height: 46px; width: auto; }

.topbar-clock {
    color: var(--muted);
    flex: 1 1 auto;
    font-size: 12px;
    text-align: center;
}

/* Notification bell, sits just left of the name. The red badge overlaps the
   bell's top-right corner and only exists in the DOM when the count is > 0. */
.topbar-bell {
    align-items: center;
    border-radius: var(--radius-sm);
    color: var(--text-dim);
    display: flex;
    flex: 0 0 auto;
    padding: var(--s1);
    position: relative;
}

.topbar-bell:hover { background-color: var(--surface-3); color: var(--accent-hover); }
.topbar-bell:focus, .topbar-bell:active { outline: none; }

.topbar-bell-badge {
    background-color: var(--danger);
    border-radius: 8px;
    color: #fff;
    font-size: 10px;
    font-weight: 700;
    height: 16px;
    line-height: 16px;
    min-width: 16px;
    padding: 0 4px;
    position: absolute;
    right: -2px;
    text-align: center;
    top: -2px;
}

.topbar-user {
    flex: 0 0 auto;
    line-height: 1.25;
}

.topbar-name { color: var(--text); font-weight: 600; }
.topbar-rank { color: var(--muted); font-size: 12px; }

/* Avatar left, name over rank to its right, caret last -- the Mafiaens Hevn
   layout. The whole strip is the dropdown trigger. */
.topbar-user-toggle {
    align-items: center;
    border-radius: var(--radius-sm);
    cursor: pointer;
    display: flex;
    flex-direction: row;
    gap: var(--s2);
    padding: var(--s1) var(--s2);
}

.topbar-avatar {
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    flex: 0 0 auto;
    height: 34px;
    object-fit: cover;
    width: 34px;
}

.topbar-user-meta {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
}

/* A small CSS caret so the strip reads as a menu, not just a label. */
.topbar-caret {
    border-top: 4px solid var(--muted);
    border-left: 4px solid transparent;
    border-right: 4px solid transparent;
    flex: 0 0 auto;
    height: 0;
    width: 0;
}

.topbar-user-toggle:hover,
.topbar-user.open .topbar-user-toggle { background-color: var(--surface-3); }

/* Bootstrap draws a light `-webkit-focus-ring-color` outline on any focused
   <a>, and clicking the toggle focuses it -- that was the pale frame around the
   whole strip. The open-state background above is the cue instead. */
.topbar-user-toggle:focus,
.topbar-user-toggle:active { outline: none; }

.topbar-user-toggle:hover .topbar-name { color: var(--accent-hover); }
.topbar-user.open .topbar-caret { border-top-color: var(--accent-hover); }

.topbar-user .dropdown-menu {
    left: auto;
    margin-top: var(--s1);
    min-width: 190px;
    right: 0;
}

.topbar-user .dropdown-menu .divider {
    background-color: var(--border-soft);
    margin: var(--s1) 0;
}

.navbar-toggle {
    background-color: transparent;
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    display: none;
    flex: 0 0 auto;
    margin: 0;
    padding: 8px 10px;
}

.navbar-toggle .icon-bar {
    background-color: var(--text-dim);
    border-radius: 1px;
    display: block;
    height: 2px;
    width: 20px;
}

.navbar-toggle .icon-bar + .icon-bar { margin-top: 4px; }

/* ---------- announcement banner ----------
   Written in the admin panel (Communication -> Announcement Banner) and shown
   above everything, on the logged-in shell and the login page alike.

   Deliberately NOT one of the .alert boxes: those are the game answering
   something the player just did, and they are dismissable. This is the game
   speaking to everyone at once, so it is a full-width strip attached to the
   topbar with no close button -- it goes away when an admin unticks it. */

.announce {
    border-bottom: 1px solid var(--border);
    /* The topbar's own gap would leave the strip floating below it. Pulled up
       against the topbar and given the gap back underneath, so the two read as
       one piece of page chrome. */
    margin: calc(var(--s4) * -1) 0 var(--s4);
    padding: var(--s2) var(--s4);
}

.announce-inner {
    margin: 0 auto;
    max-width: 1500px;   /* the topbar and layout width, so it lines up */
    text-align: center;
}

/* Rendered from BBCode, which wraps its output in paragraphs -- left alone
   they would add a blank line above and below the message inside the strip. */
.announce-inner p { margin: 0; }
.announce-inner p + p { margin-top: var(--s1); }

/* One colour per style, matching the alert palette above so the banner reads in
   the same language as the rest of the game: blue tells, amber warns, red
   stops, green is good news. The left border carries the colour at full
   strength; the fill stays dark enough for --text to stay readable. */
.announce-info    { background-color: var(--info-bg); border-bottom-color: var(--info-border); }
.announce-warning { background-color: #4a3c11;        border-bottom-color: var(--warning); }
.announce-danger  { background-color: var(--bad-bg);  border-bottom-color: var(--bad-border); }
.announce-success { background-color: var(--ok-bg);   border-bottom-color: var(--ok-border); }

/* The login page has no topbar to hang from, so it needs no negative pull --
   just a gap before the logo. */
.announce-login { margin: 0 0 var(--s4); }

/* ---------- layout ----------
   Three columns, after Mafiaens Hevn: what you DO on the left, the page in the
   middle, who you are and the world on the right. Flexbox rather than the stock
   theme's floats, so the middle column can simply take what is left. */

.layout {
    align-items: flex-start;
    display: flex;
    gap: var(--s4);
    margin: 0 auto;
    max-width: 1500px;
    padding: 0 var(--s4) var(--s5);
}

.side-bar {
    flex: 0 0 216px;
    width: 216px;
}

.game-container {
    flex: 1 1 auto;
    min-width: 0; /* lets wide tables scroll instead of stretching the column */
}

/* ---------- panels (sidebar blocks and content cards) ---------- */

.panel,
.panel-default {
    background-color: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: var(--shadow);
    margin-bottom: var(--s4);
}

.panel-heading,
.panel-default > .panel-heading {
    background-color: var(--surface-2);
    background-image: none;
    border-bottom: 1px solid var(--border-soft);
    border-radius: var(--radius) var(--radius) 0 0;
    color: var(--muted);
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.06em;
    padding: var(--s2) var(--s3);
    text-transform: uppercase;
}

.panel-body { padding: var(--s4); }

/* Panel heading with an action on the right (e.g. notifications' "Delete all"),
   without disturbing the plain-text heading elsewhere. */
.notif-heading { align-items: center; display: flex; justify-content: space-between; }
.notif-heading .btn { text-transform: none; }

/* ---------- sidebar: one see-through panel per column, groups divided ----------
   After Mafiaens Hevn: the whole left/right column is a single panel rather than
   a stack of boxes, the menu groups inside it are separated by a divider, and the
   panel is slightly translucent so the city photo shows through. Scoped to
   .side-bar so the centre game panel stays fully opaque.

   The fill sits on the GROUPS, not on the panel. A fill on the panel is still
   painted behind the admin block, so that block's red composites on top of it
   (0.82 over 0.82 is ~0.97 -- solid) and the photo stops showing through
   exactly where the red is. With the fill on each group, the admin group's red
   replaces the dark one instead of stacking on it. The groups tile the panel
   below the heading, so the column looks unchanged everywhere else. */
.side-bar .panel { background-color: transparent; }
.side-bar .list-group .menu-group { background-color: rgba(22, 22, 22, 0.82); }
/* The two main menu headings ("Handlinger", "Meny") are larger and bolder than
   the 11px content-panel headings -- they are the column titles. */
.side-bar .panel-heading { background-color: rgba(10, 10, 10, 0.55); font-size: 14px; font-weight: 700; }

/* Rows are clean within a group; the only division is between groups. */
.side-bar .list-group .list-group-item { border-top: none; }
.menu-group { padding: var(--s1) 0; }
.menu-group + .menu-group { border-top: 1px solid var(--border); }

/* ---------- list groups ---------- */

.list-group { border-radius: 0 0 var(--radius) var(--radius); margin-bottom: 0; }

.list-group-item {
    background-color: transparent;
    border: none;
    border-top: 1px solid var(--border-soft);
    color: var(--text);
    padding: var(--s2) var(--s3);
}

.list-group-item:first-child { border-top: none; }

.list-group-item .pull-right { color: var(--text-dim); }

/* Status marker on a menu row -- currently a frozen bank account. A filled
   circle rather than a bare "!" so it reads as a badge next to the label
   instead of punctuation belonging to it. */
.menu-alert {
    background: var(--danger);
    border-radius: 50%;
    color: #fff;
    display: inline-block;
    font-size: 10px;
    font-weight: 700;
    height: 15px;
    line-height: 15px;
    margin-left: var(--s1);
    text-align: center;
    vertical-align: middle;
    width: 15px;
}

a.list-group-item { color: var(--text-dim); }

a.list-group-item:hover,
a.list-group-item:focus {
    background-color: var(--accent-weak);
    color: var(--text);
}

/* The admin block is flagged red so it never reads as an ordinary menu group --
   what is behind these links changes the game for everyone, not just for the
   person clicking. The rows go white-on-red, including the hover, which would
   otherwise fall back to the blue accent and break the block. */
/* Translucent to the same degree as the other groups in the column (0.82), so
   the city photo keeps showing through the block instead of it reading as a
   solid slab pasted over the column. Selector scoped to match the specificity
   of the dark group fill above -- an unscoped .menu-group-admin loses to
   ".side-bar .list-group .menu-group" and the block comes out grey. */
.menu-group-admin,
.side-bar .list-group .menu-group-admin { background-color: rgba(237, 66, 69, 0.82); }

/* The admin block is the last group in the column, so it covers the panel's own
   rounded bottom -- square corners poking past the panel edge. Round its own
   bottom to match. */
.menu-group:last-child {
    border-bottom-left-radius: var(--radius);
    border-bottom-right-radius: var(--radius);
}

.menu-group-admin:last-child a.list-group-item:last-child {
    border-bottom-left-radius: var(--radius);
    border-bottom-right-radius: var(--radius);
}

.menu-group-admin a.list-group-item { color: #fff; }

/* !important because the sidebar row rules below paint every hovered row with
   the blue accent under the same flag; without it the admin rows light up blue
   on hover and break the block. Translucent like the group itself so the hover
   darkens the red rather than turning it into a solid bar. */
.menu-group-admin a.list-group-item:hover,
.menu-group-admin a.list-group-item:focus {
    background-color: rgba(150, 32, 35, 0.55) !important;
    color: #fff;
}

.menu-group-admin .list-group-item .pull-right { color: rgba(255, 255, 255, 0.75); }

/* The sidebar overrides the stock theme's hard-coded #111 rows. */
.side-bar .list-group {
    border: none;
    border-top: 1px solid var(--border-soft);
}

.side-bar .list-group .list-group-item {
    background-color: transparent !important;
    font-size: 12.5px;
    line-height: 20px;
    padding: 7px var(--s3);
    position: relative;
}

.side-bar .list-group .list-group-item:hover {
    background-color: var(--accent-weak) !important;
}

.side-bar .list-group .list-group-item strong {
    color: var(--muted);
    font-weight: 500;
}

.side-bar .list-group .list-group-item small {
    color: var(--text);
    font-size: 12px;
    position: relative;
    z-index: 200;
}

.side-bar .label { float: right; }

/* Health / EXP shown as a thin progress underline along the bottom of the row.
   The old design overlaid the value on a 96px bar, which broke for the Rank row
   -- its value is the rank NAME ("Nybegynner"), far too long to sit over a small
   exp bar -- and crowded Health's "100.00%". Now the value sits normally on the
   right (the .pull-right below) and the bar is just a fill line underneath. */
.side-bar .list-group .progress {
    border-radius: 0;
    bottom: 0;
    height: 3px;
    left: 0;
    position: absolute;
    right: 0;
    width: auto;
    z-index: 100;
}

.progress {
    background-color: var(--surface-3);
    border-radius: 999px;
    box-shadow: none;
    margin-bottom: 0;
    overflow: hidden;
}

.progress-bar,
.progress-bar-success {
    background-color: var(--accent);
    background-image: none;
    box-shadow: none;
    transition: width 0.3s ease;
}

.progress-bar-success { background-color: var(--success); }
.progress-bar-danger  { background-color: var(--danger); }

/* ---------- action rows (crimes, market, theft: the most-seen component) ---------- */

.crime-holder {
    background-color: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    margin-bottom: var(--s2);
    padding: var(--s3) var(--s4);
    text-align: left;
    transition: border-color 0.15s ease, background-color 0.15s ease;
}

.crime-holder:hover {
    background-color: var(--surface-2);
    border-color: var(--accent);
}

.crime-holder p { margin: 0; }

.crime-holder .action {
    color: var(--text);
    font-weight: 600;
}

.crime-holder .cooldown {
    color: var(--muted);
    font-size: 12px;
    margin-left: var(--s2);
}

.crime-holder .commit,
.crime-holder a.commit {
    background-color: var(--accent);
    border-radius: var(--radius-sm);
    color: #fff;
    float: right;
    font-size: 12px;
    font-weight: 600;
    margin-left: var(--s2);
    padding: 4px 14px;
}

/* The label sits in an <a> INSIDE span.commit, so the global
   `a { color: var(--accent) }` rule beat the white set on the span -- and
   --accent is also the span's background, which painted the text in exactly
   its own background colour and made every one of these buttons look blank.
   Affects theft, black market, gangs and inventory too, not just crimes. */
.crime-holder .commit a,
.crime-holder .commit a:hover,
.crime-holder .commit a:focus { color: #fff; }

.crime-holder .commit:hover { background-color: var(--accent-hover); color: #fff; }

/* ---------- crime picker (Mafiaens Hevn layout: choose a row, then commit) ----------
   Each row is a single flex <label>, not a table row. It used to be a <td> with
   the label and a SEPARATE <td> for the chance/price -- so only the first cell
   was clickable and hovered, and the whole right half of the row (the marked
   dark strip) did nothing. A flex label makes the entire row one click target. */
.crime-picker { margin-bottom: var(--s4); }

.crime-head {
    border-bottom: 1px solid var(--border);
    color: var(--text);
    display: flex;
    font-weight: 600;
    padding: var(--s2) var(--s3);
}

.crime-option {
    align-items: center;
    border-bottom: 1px solid var(--border-soft);
    color: var(--text-dim);
    cursor: pointer;
    display: flex;
    margin: 0;
    padding: var(--s2) var(--s3);
}

.crime-option input { flex: 0 0 auto; margin: 0 var(--s2) 0 0; }

/* Name fills the row and pushes the chance/price to the right edge. */
.crime-name { flex: 1 1 auto; }
.crime-chance { flex: 0 0 auto; margin-left: auto; text-align: right; white-space: nowrap; }
.crime-head .crime-chance { color: var(--text); }
.crime-option .crime-chance { color: var(--text-dim); }

/* The action name is the row's title: bold and full-strength, at 12px. */
.crime-option .crime-name {
    color: var(--text);
    font-size: 12px;
    font-weight: 600;
}

.crime-option:hover { background-color: var(--surface-2); }
.crime-option:has(input:checked) { background-color: var(--accent-weak); }
.crime-option:has(input:checked) .crime-chance { color: var(--text); }

.crime-submit { text-align: right; }

/* ---------- hjelpekort ----------
   Started life as .rob-help on the one page that had an explanation. Every page
   whose numbers an admin can retune needs the same thing, so the classes are
   generic and every module reuses these -- there is one place to restyle a help
   card, not eight. */

/* The "?" sits at the far end of the heading, opposite the title. */
.help-heading { align-items: center; display: flex; justify-content: space-between; }
.help-btn {
    background: none;
    border: 1px solid var(--border);
    border-radius: 50%;
    color: var(--text-dim);
    font-size: 11px;
    font-weight: 700;
    height: 20px;
    line-height: 1;
    padding: 0;
    width: 20px;
}
.help-btn:hover { border-color: var(--accent-hover); color: var(--text); }

.rob-intro { color: var(--text-dim); margin-bottom: var(--s4); }

.rob-field { margin-bottom: var(--s4); }
.rob-label {
    color: var(--text);
    display: block;
    font-weight: 600;
    margin-bottom: var(--s2);
}

/* Radio rows, deliberately lighter than .crime-option: there are only two of
   them and they are a question, not a list of actions to compare. */
.rob-option {
    align-items: center;
    color: var(--text-dim);
    cursor: pointer;
    display: flex;
    font-weight: 400;
    gap: var(--s2);
    margin: 0 0 var(--s1);
}
.rob-option input { margin: 0; }
.rob-option:hover { color: var(--text); }

.rob-field .form-control { margin-bottom: 0; }
.rob-cost { color: var(--muted); font-size: 12px; }
.rob-submit { text-align: right; }

.help-card h5 {
    color: var(--accent-hover);
    font-size: 13px;
    font-weight: 700;
    margin: var(--s4) 0 var(--s2);
}
.help-card p,
.help-card li { color: var(--text-dim); }
.help-card ul { margin: 0 0 var(--s2); padding-left: var(--s4); }

/* Auto width: these tables hold two or three short columns, and stretched to
   the full modal they read as a gap with numbers at either end. */
.help-table { margin-bottom: 0; width: auto; }

/* A help table can outgrow a phone -- the car list carries four columns. Let it
   scroll inside the modal instead of widening it. */
.help-scroll { -webkit-overflow-scrolling: touch; overflow-x: auto; }

/* Travel: the two travel buttons (ownership uses the shared propertyOwnership
   block, styled like the bullet factory / casino pages). */
.property-ownership { color: var(--text-dim); display: block; margin-top: var(--s3); }
.travel-submit { display: flex; gap: var(--s2); justify-content: flex-end; }

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

.btn {
    background-image: none;
    border: 1px solid transparent;
    border-radius: var(--radius-sm);
    box-shadow: none;
    font-size: 13px;
    font-weight: 600;
    padding: 7px 16px;
    text-shadow: none;
    transition: background-color 0.15s ease, border-color 0.15s ease;
}

.btn:focus, .btn:active:focus { outline: 2px solid var(--accent-weak); outline-offset: 1px; }

.btn-default {
    background-color: var(--surface-3);
    border-color: var(--border);
    color: var(--text);
}

.btn-default:hover, .btn-default:focus {
    background-color: var(--surface-2);
    border-color: var(--accent);
    color: var(--text);
}

.btn-primary, .btn-info {
    background-color: var(--accent);
    border-color: var(--accent);
    color: #fff;
}

.btn-primary:hover, .btn-info:hover,
.btn-primary:focus, .btn-info:focus {
    background-color: var(--accent-hover);
    border-color: var(--accent-hover);
    color: #fff;
}

.btn-success { background-color: var(--success); border-color: var(--success); color: #06281a; }
.btn-success:hover { background-color: #35b87d; border-color: #35b87d; color: #06281a; }

.btn-danger { background-color: var(--danger); border-color: var(--danger); color: #fff; }
.btn-danger:hover { background-color: #dc5850; border-color: #dc5850; color: #fff; }

.btn-warning { background-color: var(--warning); border-color: var(--warning); color: #2a2000; }
.btn-warning:hover { background-color: #d29e07; border-color: #d29e07; color: #2a2000; }

/* Mafiaens Hevn's submit button: vertical gradient, lit teal rim, glowing
   label. MUST stay below the base `.btn` block -- both are single-class, so
   whichever comes last wins, and .btn sets `background-image: none` and
   `text-shadow: none`. Defined above .btn, those two blanked the gradient and
   the glow, leaving the button invisible until :hover swapped in its own
   background. This is a modifier; a modifier belongs after its base. */
/* No text glow: MH lights its label with a text-shadow, but a crisp label reads
   better here. The base .btn already sets text-shadow: none; this keeps .btn-mh
   in line rather than reinstating the glow. */
.btn-mh, .btn-mh:focus {
    background: linear-gradient(to bottom, var(--btn-from) 0%, var(--btn-to) 100%);
    border: 1px solid var(--btn-border);
    color: var(--btn-text);
    text-shadow: none;
}

.btn-mh:hover {
    background: linear-gradient(to bottom, var(--btn-to) 0%, var(--btn-from) 100%);
    border-color: var(--accent-hover);
    color: #fff;
}

/* ---------- admin debug modal ---------- */

/* Bootstrap's modal ships light; restyle it for the dark theme. */
.modal-content {
    background-color: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: 0 8px 30px rgba(0, 0, 0, 0.5);
    color: var(--text);
}
.modal-header {
    border-bottom: 1px solid var(--border-soft);
    padding: var(--s3) var(--s4);
}
.modal-title { color: var(--text); font-size: 15px; font-weight: 600; }
.modal-header .close { color: var(--muted); opacity: 0.8; text-shadow: none; }
.modal-header .close:hover { color: var(--text); opacity: 1; }
.modal-body { padding: var(--s4); }
.modal-backdrop.in { opacity: 0.6; }

/* ---------- Adminverktøy modal ---------- */

/* Two screens share one modal body; the hidden attribute does the switching. */
.admin-screen[hidden] { display: none; }

.admin-field label {
    color: var(--muted);
    display: block;
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.06em;
    margin-bottom: var(--s1);
    text-transform: uppercase;
}
.admin-field .form-control { margin-bottom: 0; }

/* Search box + results on the left, recent queries in a fixed rail on the
   right -- narrow enough that it never competes with the result list for
   attention. */
.admin-search-layout { display: flex; gap: var(--s4); }
.admin-search-main { flex: 1 1 auto; min-width: 0; }
.admin-recent { border-left: 1px solid var(--border-soft); flex: 0 0 160px; padding-left: var(--s4); }
.admin-recent .admin-section-title { margin-top: 0; }

/* Search results. Capped height so a broad query cannot push the modal past
   the viewport -- the list scrolls instead. */
.admin-results {
    list-style: none;
    margin: var(--s3) 0 0;
    max-height: 320px;
    overflow-y: auto;
    padding: 0;
}
.admin-result {
    align-items: baseline;
    border: 1px solid var(--border-soft);
    border-radius: var(--radius-sm);
    cursor: pointer;
    display: flex;
    gap: var(--s3);
    justify-content: space-between;
    margin-bottom: var(--s2);
    padding: var(--s2) var(--s3);
}
.admin-result:hover { background: var(--accent-weak); border-color: var(--border); }
.admin-result.is-dead { opacity: 0.55; }
.admin-result-name { color: var(--text); font-weight: 600; }
.admin-result-meta { color: var(--muted); font-size: 11px; text-align: right; }
.admin-result-empty { color: var(--muted); font-size: 12px; padding: var(--s2) 0; }

/* Recent search queries. Plain text buttons -- clicking one repeats that
   search rather than jumping anywhere, since a query can match many users. */
.admin-recent-list { list-style: none; margin: var(--s3) 0 0; padding: 0; }
.admin-recent-item {
    background: none;
    border: 0;
    color: var(--text-dim);
    cursor: pointer;
    display: block;
    font-size: 12px;
    padding: var(--s1) 0;
    text-align: left;
    width: 100%;
}
.admin-recent-item:hover { color: var(--text); }
.admin-recent-empty { color: var(--muted); font-size: 11px; }

@media (max-width: 600px) {
    .admin-search-layout { flex-direction: column; }
    .admin-recent { border-left: 0; border-top: 1px solid var(--border-soft); padding-left: 0; padding-top: var(--s3); }
}

/* Who is selected, plus the way back to the search screen. */
.admin-selected {
    align-items: center;
    border-bottom: 1px solid var(--border-soft);
    display: flex;
    gap: var(--s3);
    margin-bottom: var(--s3);
    padding-bottom: var(--s3);
}
.admin-selected-who { display: flex; flex-direction: column; }
.admin-selected-who strong { color: var(--text); font-size: 15px; }
.admin-selected-meta { color: var(--muted); font-size: 11px; }

/* Result of the last action, in place of the old page reload. */
.admin-alert {
    border: 1px dashed transparent;
    border-radius: var(--radius-sm);
    font-size: 13px;
    margin-bottom: var(--s3);
    padding: var(--s2) var(--s3);
}
.admin-alert[hidden] { display: none; }
.admin-alert.is-ok  { background: var(--ok-bg);  border-color: var(--ok-border);  color: var(--text); }
.admin-alert.is-bad { background: var(--bad-bg); border-color: var(--bad-border); color: var(--text); }

.admin-section {
    border-top: 1px solid var(--border-soft);
    margin-top: var(--s3);
    padding-top: var(--s3);
}
.admin-section-title {
    color: var(--accent-hover);
    font-size: 12px;
    font-weight: 700;
    letter-spacing: 0.04em;
    margin: 0 0 var(--s2);
    text-transform: uppercase;
}
.admin-section-danger .admin-section-title { color: var(--danger); }

/* Every tool is one row: input on the left, its button on the right. The
   buttons share a fixed width so the whole column lines up. */
.admin-row {
    align-items: center;
    display: flex;
    gap: var(--s2);
    margin-bottom: var(--s2);
}
.admin-row .form-control { flex: 1 1 auto; margin-bottom: 0; }
.admin-row .btn { flex: 0 0 190px; }
.admin-row-label { color: var(--muted); flex: 1 1 auto; font-size: 12px; }

.admin-hint { color: var(--muted); font-size: 11px; margin: var(--s2) 0 0; }

/* Tools on the left, the selected player's live numbers on the right. */
.admin-tools-layout {
    display: grid;
    gap: var(--s3);
    grid-template-columns: minmax(0, 1fr) 210px;
}
.admin-tools-main { min-width: 0; }

/* Two tools per row. Stacked one per row, Ressurser alone pushed the sections
   below it off the bottom of the modal. */
.admin-grid {
    display: grid;
    gap: var(--s2);
    grid-template-columns: repeat(2, minmax(0, 1fr));
}
.admin-grid .admin-row { margin-bottom: 0; }
/* The fixed 190px button only lines up in a full-width row; in a half-width
   grid cell it leaves the input too narrow to read. */
.admin-grid .admin-row .btn { flex: 0 0 auto; }

/* Override toggles. Lit when on, so the dangerous state is the visible one. */
.admin-toggle {
    align-items: center;
    background: var(--surface-2);
    border: 1px solid var(--border-soft);
    border-radius: var(--radius-sm);
    color: var(--text-dim);
    display: flex;
    font-size: 12px;
    gap: var(--s2);
    justify-content: space-between;
    padding: var(--s2) var(--s3);
    text-align: left;
    width: 100%;
}
.admin-toggle:hover { border-color: var(--accent-hover); color: var(--text); }
.admin-toggle-state { color: var(--muted); font-weight: 700; letter-spacing: 0.04em; }
.admin-toggle.is-on { border-color: var(--warning); color: var(--text); }
.admin-toggle.is-on .admin-toggle-state { color: var(--warning); }
.admin-toggle[disabled] { opacity: 0.6; }

.admin-info {
    border-left: 1px solid var(--border-soft);
    padding-left: var(--s3);
}
.admin-info-list {
    display: grid;
    gap: 2px var(--s2);
    grid-template-columns: auto minmax(0, 1fr);
    margin: 0;
}
.admin-info-list dt {
    color: var(--muted);
    font-size: 11px;
    font-weight: 400;
    white-space: nowrap;
}
.admin-info-list dd {
    color: var(--text);
    font-size: 12px;
    margin: 0;
    overflow: hidden;
    text-align: right;
    text-overflow: ellipsis;
}
.admin-info-list dd.is-dead { color: var(--danger); font-weight: 700; }
.admin-info-list dd.admin-info-loading { color: var(--muted); }

/* Audit trail under the info list. One line per action: time, what happened,
   and which admin did it -- the last one dimmed, since the usual question is
   "what has been done to this account", not "by whom". */
.admin-log-title { margin-top: var(--s3); }
.admin-log-list {
    display: flex;
    flex-direction: column;
    gap: var(--s1);
    list-style: none;
    margin: 0;
    padding: 0;
}
.admin-log-entry {
    border-top: 1px solid var(--border-soft);
    display: grid;
    font-size: 11px;
    gap: 0 var(--s2);
    grid-template-columns: auto minmax(0, 1fr);
    padding-top: var(--s1);
}
.admin-log-when { color: var(--muted); white-space: nowrap; }
.admin-log-what { color: var(--text); overflow-wrap: anywhere; }
.admin-log-who { color: var(--muted); grid-column: 2; }
.admin-log-empty,
.admin-log-loading { color: var(--muted); font-size: 11px; }

/* The info column has nowhere to go on a narrow screen, so it moves under
   the tools rather than squeezing them. */
@media (max-width: 900px) {
    .admin-tools-layout { grid-template-columns: minmax(0, 1fr); }
    .admin-info {
        border-left: 0;
        border-top: 1px solid var(--border-soft);
        padding-left: 0;
        padding-top: var(--s3);
    }
}

@media (max-width: 600px) {
    .admin-row { flex-wrap: wrap; }
    .admin-row .btn { flex: 1 1 100%; }
    .admin-row-label { flex: 1 1 100%; }
    .admin-grid { grid-template-columns: minmax(0, 1fr); }
}

/* ---------- headquarters (landing page) ---------- */

.hq-intro { color: var(--text-dim); margin: 0; }

/* Premium panel: a gold-accented card shown only while a membership is active. */
.hq-premium { border-color: var(--warning); }
.hq-premium .panel-heading { color: var(--warning); }

.hq-premium-status { align-items: center; color: var(--text); display: flex; flex-wrap: wrap; gap: var(--s2); margin: 0 0 var(--s3); }
.hq-premium-package { color: var(--text); font-weight: 600; }
.hq-premium-expiry { color: var(--text-dim); }

.hq-premium-badge {
    background-color: var(--warning);
    border-radius: var(--radius-sm);
    color: #2a2000;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.04em;
    margin-right: var(--s2);
    padding: 2px 8px;
    text-transform: uppercase;
}

.hq-benefit {
    border-top: 1px solid var(--border-soft);
    padding: var(--s2) 0;
}
.hq-benefit:last-child { padding-bottom: 0; }

.hq-benefit-title { color: var(--text); display: block; }
.hq-benefit-desc { color: var(--text-dim); font-size: 13px; }

/* Rankbar: a filled track with the percentage centred over it, and a row of
   meta below -- current rank on the left, XP in the middle, next rank right. */
.rankbar-track {
    background-color: var(--surface-3);
    border: 1px solid var(--border);
    border-radius: 999px;
    height: 26px;
    overflow: hidden;
    position: relative;
}

.rankbar-fill {
    background-color: var(--accent);
    height: 100%;
    transition: width 0.4s ease;
}

.rankbar-perc {
    color: var(--text);
    font-size: 13px;
    font-weight: 600;
    left: 0;
    line-height: 26px;
    position: absolute;
    right: 0;
    text-align: center;
    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);
    top: 0;
}

.rankbar-meta {
    color: var(--text-dim);
    display: flex;
    font-size: 12px;
    justify-content: space-between;
    margin-top: var(--s2);
}

.rankbar-rank { color: var(--text); font-weight: 600; }
.rankbar-next { color: var(--muted); }
.rankbar-xp { color: var(--text-dim); }

/* Tips card: shown only to first-rank players, one column per tip. */
.hq-tips .panel-heading { color: var(--accent); }

.hq-tip-grid {
    display: grid;
    gap: var(--s3);
    grid-template-columns: repeat(3, 1fr);
}
@media (max-width: 767px) {
    .hq-tip-grid { grid-template-columns: 1fr; }
}

.hq-tip {
    align-items: flex-start;
    display: flex;
    gap: var(--s2);
}

.hq-tip-icon {
    color: var(--accent);
    flex: 0 0 auto;
    font-size: 18px;
    line-height: 1.4;
}

.hq-tip-body { display: flex; flex-direction: column; }
.hq-tip-title { color: var(--text); }
.hq-tip-text { color: var(--text-dim); font-size: 13px; margin-top: 2px; }

/* Latest events: a scrollable stack of dated news items. */
.hq-events { max-height: 360px; overflow-y: auto; }

.hq-event {
    border-bottom: 1px solid var(--border-soft);
    padding: var(--s2) 0;
}
.hq-event:first-child { padding-top: 0; }
.hq-event:last-child { border-bottom: none; }

.hq-event-title { color: var(--text); font-weight: 600; }
.hq-event-date { color: var(--muted); font-size: 11px; }
.hq-event-text { color: var(--text-dim); font-size: 13px; margin-top: var(--s1); }

/* ---------- property overview (Mafiaens Hevn "Byoversikt" city cards) ---------- */

/* One card per property type; the type name heads the card. */
.prop-head .prop-title { color: var(--text); font-size: 14px; letter-spacing: 0; text-transform: none; }

/* Two cities per row; collapses to one on narrow panels. */
.prop-rows {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
}

.prop-row {
    align-items: center;
    border-top: 1px solid var(--border-soft);
    display: flex;
    justify-content: space-between;
    padding: var(--s2) var(--s3);
}
/* A left cell also gets a divider from its right neighbour. */
.prop-row:nth-child(odd) { border-right: 1px solid var(--border-soft); }

.prop-row-city  { color: var(--text-dim); }
.prop-row-owner { color: var(--text); font-weight: 600; }

/* Vacant properties are marked, not left blank. */
.prop-row-vacant {
    background-color: var(--accent-weak);
    border-radius: var(--radius-sm);
    color: var(--accent-hover);
    font-size: 12px;
    font-weight: 600;
    padding: 1px 8px;
}

@media (max-width: 767px) {
    .prop-rows { grid-template-columns: 1fr; }
    .prop-row:nth-child(odd) { border-right: none; }
}

/* ---------- coin flip ---------- */
.coinflip-form label { color: var(--text); display: block; font-weight: 600; margin-top: var(--s3); }
.coinflip-sides { display: flex; gap: var(--s4); margin: var(--s1) 0 0; }
.coinflip-side { align-items: center; color: var(--text-dim); display: flex; font-weight: 400; gap: var(--s2); margin: 0; }
.coinflip-side input { margin: 0; }
.coinflip-form .form-control { margin-top: var(--s1); max-width: 320px; }
.coinflip-submit { margin-top: var(--s3); }

/* ---------- bank ---------- */

/* Kontooversikten: én ramme rundt hele lista, med skillelinjer mellom radene,
   slik en nettbank stiller opp kontoene sine. Bevisst ikke ett kort per konto --
   det er oppstillingen under hverandre som gjør at det leses som en kontoliste
   og ikke som fire løsrevne bokser. */
.nb-accounts {
    background-color: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    margin-bottom: var(--s4);
    overflow: hidden;
}

.nb-accounts-head {
    align-items: baseline;
    background-color: var(--surface-2);
    border-bottom: 1px solid var(--border);
    display: flex;
    gap: var(--s3);
    justify-content: space-between;
    padding: var(--s3) var(--s4);
}

.nb-accounts-title {
    color: var(--accent);
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 0.08em;
    text-transform: uppercase;
}

.nb-accounts-total {
    color: var(--muted);
    font-size: 12px;
    white-space: nowrap;
}

.nb-accounts-total strong {
    color: var(--text);
    font-size: 15px;
    margin-left: var(--s2);
}

.nb-account-list {
    list-style: none;
    margin: 0;
    padding: 0;
}

.nb-account {
    align-items: center;
    border-top: 1px solid var(--border-soft);
    display: flex;
    gap: var(--s4);
    justify-content: space-between;
    padding: var(--s3) var(--s4);
}

.nb-account:first-child { border-top: none; }

.nb-account-id { min-width: 0; }

.nb-account-name {
    color: var(--text);
    display: block;
    font-size: 15px;
    font-weight: 600;
}

.nb-account-name a { color: var(--accent-hover); }

/* Kontonummeret er pynt, og skal leses som pynt: tabulærtall så sifrene står
   i kolonne fra rad til rad, og dempet farge så det ikke konkurrerer med navnet. */
.nb-account-number {
    color: var(--muted);
    display: block;
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 11px;
    letter-spacing: 0.04em;
}

.nb-account-note {
    color: var(--text-dim);
    display: block;
    font-size: 12px;
    margin-top: var(--s1);
}

.nb-account-figures {
    flex-shrink: 0;
    text-align: right;
}

.nb-account-balance {
    color: var(--text);
    display: block;
    font-size: 18px;
    font-weight: 600;
    white-space: nowrap;
}

/* Rentemerket. Grønt bare når det faktisk løper renter -- ellers er det en
   nøytral opplysning, og et grønt merke på "Ingen rente" ville lovet noe. */
.nb-account-rate {
    display: inline-block;
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.04em;
    margin-top: var(--s1);
    white-space: nowrap;
}

.nb-rate-on {
    background-color: rgba(62, 207, 142, 0.12);
    border: 1px solid rgba(62, 207, 142, 0.35);
    border-radius: var(--radius-sm);
    color: var(--success);
    padding: 1px var(--s2);
}

.nb-rate-none { color: var(--muted); }

/* Hovedkontoen får en tydelig venstrekant, slik nettbanker markerer den kontoen
   siden faktisk handler om. */
.nb-account-main-account { box-shadow: inset 3px 0 0 var(--accent); }

.nb-account-shared .nb-account-balance { color: var(--text-dim); }

/* Låst konto: dempet, men ikke skjult. Den står der for å vise at det finnes
   mer enn det man har -- forsvinner den helt, er det ingenting å strekke seg
   etter. */
.nb-account-locked { opacity: 0.55; }
.nb-account-locked .nb-account-balance {
    color: var(--muted);
    font-size: 14px;
    font-weight: 400;
    font-style: italic;
}

@media (max-width: 600px) {
    .nb-account { align-items: flex-start; flex-direction: column; gap: var(--s2); }
    .nb-account-figures { text-align: left; }
}

/* Vilkårene øverst i flytt-kortet: hvitvasking, rente og rentefrekvens som tre
   tall ved siden av hverandre. Samme etikett/verdi-oppsett som kontooversikten,
   så de to kortene leses som samme side. */
.nb-terms {
    background-color: var(--surface-2);
    border: 1px solid var(--border-soft);
    border-radius: var(--radius-sm);
    display: flex;
    flex-wrap: wrap;
    gap: var(--s5);
    margin-bottom: var(--s4);
    padding: var(--s3) var(--s4);
}

.nb-term-label {
    color: var(--muted);
    display: block;
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
}

.nb-term-value {
    color: var(--text);
    font-size: 16px;
    font-weight: 600;
    white-space: nowrap;
}

/* Inn og ut i samme kort: beløp og knapp på hver sin linje, knappene like brede
   så de står rett under hverandre og fargen er det eneste som skiller dem. */
.nb-move-row {
    display: flex;
    gap: var(--s3);
}

.nb-move-row + .nb-move-row { margin-top: var(--s3); }

.nb-move-row .form-control { flex: 1 1 auto; }

.nb-move-row .btn {
    flex: 0 0 140px;
    font-weight: 600;
}

/* Grønn inn, rød ut -- de samme to fargene som beløpene i transaksjonslista,
   så retningen på en handling ser lik ut over hele siden. Fyllet er dempet og
   kanten er den mettede fargen: en flat, sterk knappeflate ville vært det
   eneste stedet i temaet med den intensiteten. */
.nb-btn-in,
.nb-btn-out {
    border-radius: var(--radius-sm);
    border-style: solid;
    border-width: 1px;
    transition: background-color 0.15s, box-shadow 0.15s;
}

.nb-btn-in {
    background-color: rgba(62, 207, 142, 0.14);
    border-color: rgba(62, 207, 142, 0.45);
    color: var(--success);
}

.nb-btn-in:hover,
.nb-btn-in:focus {
    background-color: rgba(62, 207, 142, 0.24);
    box-shadow: 0 0 6px rgba(62, 207, 142, 0.35);
    color: var(--success);
}

.nb-btn-out {
    background-color: rgba(242, 101, 92, 0.14);
    border-color: rgba(242, 101, 92, 0.45);
    color: var(--danger);
}

.nb-btn-out:hover,
.nb-btn-out:focus {
    background-color: rgba(242, 101, 92, 0.24);
    box-shadow: 0 0 6px rgba(242, 101, 92, 0.35);
    color: var(--danger);
}

@media (max-width: 480px) {
    .nb-terms { gap: var(--s4); }
    .nb-move-row { flex-direction: column; }
    .nb-move-row .btn { flex: 1 1 auto; }
}

/* Betalingslinja: mottaker, beløp og knapp ved siden av hverandre. Bootstrap
   stabler dem selv under 768 px, så marginen her er bare for den stablingen. */
.nb-pay > div { margin-bottom: var(--s2); }

.bank-transactions { margin-bottom: 0; }
.bank-transactions td { padding: var(--s2) var(--s3); vertical-align: middle; }
.bank-transactions .txn-date { color: var(--muted); font-size: 12px; white-space: nowrap; }
.bank-transactions .txn-desc { color: var(--text); }
.bank-transactions .txn-amount { font-weight: 600; text-align: right; white-space: nowrap; }

/* Incoming green, outgoing red -- the same success/danger cues used elsewhere. */
.bank-transactions .txn-in  { color: var(--success); }
.bank-transactions .txn-out { color: var(--danger); }

/* ---------- forms ---------- */

.form-group { margin-bottom: var(--s3); }

.form-control {
    background-color: var(--surface-2);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    box-shadow: none;
    color: var(--text);
    font-size: 14px;
    height: auto;
    padding: 8px 12px;
}

.form-control:focus {
    border-color: var(--accent);
    box-shadow: 0 0 0 3px var(--accent-weak);
    outline: none;
}

.form-control::placeholder { color: var(--muted); }
.form-control::-webkit-input-placeholder { color: var(--muted); }

label { color: var(--text-dim); font-size: 13px; font-weight: 500; }

select.form-control option { background-color: var(--surface); color: var(--text); }

/* ---------- alerts ---------- */

.alert {
    border: 1px solid var(--border);
    border-left-width: 3px;
    border-radius: var(--radius-sm);
    margin-bottom: var(--s4);
    padding: var(--s3) var(--s4);
    text-align: left;
}

/* MH styles these as a flat fill with a dashed border, not a tinted wash with
   an accent stripe -- so the border shorthand has to be reset here, otherwise
   .alert's solid 1px/3px-left rule above still wins on the sides. */
.alert-success { background-color: var(--ok-bg);   border: 1px dashed var(--ok-border);   color: var(--text); }
.alert-danger,
.alert-error   { background-color: var(--bad-bg);  border: 1px dashed var(--bad-border);  color: var(--text); }
.alert-warning,
.alert-info    { background-color: var(--info-bg); border: 1px dashed var(--info-border); color: var(--text); }
.alert-info { background-color: var(--accent-weak); border-left-color: var(--accent); color: var(--text); }

.alert .close { color: var(--muted); opacity: 0.7; text-shadow: none; }
.alert .close:hover { color: var(--text); opacity: 1; }

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

.table { color: var(--text); margin-bottom: 0; }

.table > thead > tr > th {
    border-bottom: 1px solid var(--border);
    color: var(--muted);
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.05em;
    padding: var(--s2) var(--s3);
    text-transform: uppercase;
}

.table > tbody > tr > td {
    border-top: 1px solid var(--border-soft);
    padding: var(--s2) var(--s3);
    vertical-align: middle;
}

/* The striped rows have to be repainted on the CELLS, not the row. The minified
   Bootstrap we actually serve sets #f9f9f9 on "tr:nth-child(odd) > td", and a
   background on a td paints over the tr's own no matter which sheet loads last
   -- which left every other row of the bullet factory table white-on-white.
   nth-child, not nth-of-type, to match the rule being overridden. */
.table-striped > tbody > tr:nth-child(odd) > td,
.table-striped > tbody > tr:nth-child(odd) > th { background-color: var(--surface-2); }

.table-hover > tbody > tr:hover { background-color: var(--accent-weak); }
.table-bordered, .table-bordered > tbody > tr > td, .table-bordered > thead > tr > th { border-color: var(--border); }

/* ---------- tabs, pills, pagination, labels ---------- */

.nav-tabs { border-bottom: 1px solid var(--border); }

.nav-tabs > li > a {
    border: none;
    border-bottom: 2px solid transparent;
    border-radius: 0;
    color: var(--muted);
    font-weight: 500;
    margin-right: var(--s2);
    padding: var(--s2) var(--s3);
}

.nav-tabs > li > a:hover { background-color: transparent; border-bottom-color: var(--border); color: var(--text); }

.nav-tabs > li.active > a,
.nav-tabs > li.active > a:hover,
.nav-tabs > li.active > a:focus {
    background-color: transparent;
    border: none;
    border-bottom: 2px solid var(--accent);
    color: var(--text);
}

.nav-pills > li > a { border-radius: var(--radius-sm); color: var(--text-dim); }
.nav-pills > li > a:hover { background-color: var(--surface-2); color: var(--text); }
.nav-pills > li.active > a,
.nav-pills > li.active > a:hover { background-color: var(--accent); color: #fff; }

.pagination > li > a,
.pagination > li > span {
    background-color: var(--surface);
    border-color: var(--border);
    color: var(--text-dim);
}

.pagination > li > a:hover { background-color: var(--surface-2); border-color: var(--accent); color: var(--text); }

.pagination > .active > a,
.pagination > .active > span,
.pagination > .active > a:hover {
    background-color: var(--accent);
    border-color: var(--accent);
    color: #fff;
}

.label { border-radius: 999px; font-size: 11px; font-weight: 600; padding: 3px 9px; }
.label-default { background-color: var(--surface-3); color: var(--text-dim); }
.label-success { background-color: var(--success); color: #06281a; }
.label-danger  { background-color: var(--danger); color: #fff; }
.label-warning { background-color: var(--warning); color: #2a2000; }
.label-info    { background-color: var(--accent); color: #fff; }

.dropdown-menu {
    background-color: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius-sm);
    box-shadow: 0 6px 18px rgba(0, 0, 0, 0.25);
}

.dropdown-menu > li > a { color: var(--text-dim); padding: var(--s2) var(--s3); }
.dropdown-menu > li > a:hover { background-color: var(--accent-weak); color: var(--text); }

.img-thumbnail { background-color: var(--surface-2); border-color: var(--border); border-radius: var(--radius-sm); }

.well { background-color: var(--surface-2); border-color: var(--border); border-radius: var(--radius-sm); box-shadow: none; }

/* ---------- login / register ---------- */

/* The full wordmark, sitting above the login form. It is wider than the
   380px form, so it is capped against the viewport rather than the form --
   max-width keeps it inside the screen on a phone, max-height keeps it from
   towering over the form on a desktop. */
/* The full wordmark, sitting above the login form. Capped against the viewport
   rather than the 380px form, since it is wider than the form -- max-width keeps
   it on screen on a phone, max-height keeps it below the artwork's own 133px so
   it is always scaled down, never up. */
.login-logo { padding: var(--s5) var(--s4) var(--s4); text-align: center; }
.login-logo img { max-height: 104px; max-width: 100%; width: auto; }

.login-form {
    background-color: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: var(--shadow);
    margin: 30px auto;
    max-width: 380px;
    padding: 2px;
}

.login-form .btn { width: 100%; }

/* ---------- misc ---------- */

.new { color: var(--accent); font-weight: 600; }

.padding { padding: var(--s4); }

.no-scroll { overflow: hidden; }

::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: var(--bg); }
::-webkit-scrollbar-thumb { background: var(--surface-3); border-radius: 999px; }
::-webkit-scrollbar-thumb:hover { background: var(--border); }

/* ---------- treningssenter ----------
   Lå i modulens egen training.styles.css. Den lastes uversjonert av page.php,
   så en endring nådde bare de som hardrefreshet -- resten satt igjen med en
   gammel kopi og fikk en side som så ødelagt ut uten at noe var galt i koden.
   Temaets style.css er versjonert på filens mtime, så her oppdaterer den seg. */

/* Venstre kolonne: de to tallene side om side. De måler forskjellige ting og
   tjenes inn på hver sin måte, så de får like mye plass -- ingen av dem er en
   fotnote til den andre. */
.train-scores {
    display: flex;
    gap: var(--s2);
    margin-bottom: var(--s4);
    padding: var(--s2) 0;
}

.train-score {
    align-items: center;
    display: flex;
    flex: 1 1 0;
    flex-direction: column;
    /* min-width: 0 -- et flex-element nekter ellers å krympe under innholdet,
       og et femsifret tall ville dyttet kolonnen bredere enn panelet. */
    min-width: 0;
    text-align: center;
}

.train-score-value {
    color: var(--accent-hover);
    font-size: 34px;
    font-weight: 700;
    line-height: 1.1;
    /* Sifre i samme bredde: uten dette hopper tallet sidelengs hver gang det
       endrer seg, siden 1 er smalere enn 8 i de fleste skrifter. */
    font-variant-numeric: tabular-nums;
    font-feature-settings: "tnum";
}

/* Etiketten er dempet og liten: tallet er det du leser, ordet er bare der for
   å si hvilket av de to det er. */
.train-score-label { color: var(--muted); font-size: 12px; letter-spacing: 0.02em; }

/* De to grenene ligger side om side i ett kort, med hver sin overskrift.
   Overskriften er det eneste som skiller dem, siden begge kolonnene har de
   samme tre valgene. Hva hver gren faktisk bygger står i hjelpekortet -- siden
   selv holder seg til navnene. */

/* Bootstrap-raden bærer -15px sidemarger som panelkroppens padding skal
   oppheve; her ligger den inni en panel-body, så de må nulles eller stikker
   kolonnene ut forbi kanten. */
.train-groups { margin-left: 0; margin-right: 0; }
.train-groups > [class*="col-"] { padding-left: 0; padding-right: var(--s2); }
.train-groups > [class*="col-"]:last-child { padding-left: var(--s2); padding-right: 0; }

.train-group-head {
    border-bottom: 1px solid var(--border);
    margin-bottom: var(--s2);
    padding-bottom: var(--s1);
}

.train-group-name { color: var(--text); display: block; font-weight: 600; }

/* Valgene. Radene bærer bare navnet -- utbytte og ventetid står i hjelpekortet
   -- så de er lave og tette. Hele raden er klikkflate, ikke bare radioknappen. */
.train-option {
    align-items: center;
    border: 1px solid transparent;
    border-radius: var(--radius-sm);
    color: var(--text-dim);
    cursor: pointer;
    display: flex;
    font-weight: 400;
    gap: var(--s2);
    margin: 0 0 var(--s1);
    padding: var(--s2) var(--s3);
}

.train-option:hover { background-color: var(--surface-2); color: var(--text); }
.train-option input { margin: 0; }
.train-option-name { color: var(--text); font-weight: 600; }

/* Valgt rad markeres. Uten dette var den blå prikken i radioknappen det eneste
   som skilte den valgte fra de fem andre, og på en bred skjerm ligger den langt
   fra navnet den hører til. :has() lar raden svare på sin egen input. */
.train-option:has(input:checked) {
    background-color: var(--accent-weak);
    border-color: var(--border);
}

.train-submit { margin-top: var(--s3); text-align: right; }

/* Stablet på mobil har venstre kolonne allerede sin egen panelmarg, så den
   doble avstanden mellom de to panelene blir for stor. */
@media (max-width: 991px) {
    .train-score-value { font-size: 26px; }
}

/* Dagens mål. Ligger mellom divisjonen og resten av tallene, fordi det er den
   ene tingen på siden som haster -- alt annet kan gjøres i morgen. */
.train-goal {
    border-top: 1px solid var(--border);
    margin-top: 0;
    padding-top: var(--s3);
}

.train-goal-head {
    align-items: baseline;
    display: flex;
    justify-content: space-between;
    margin-bottom: var(--s1);
}

.train-goal-title { color: var(--text); font-weight: 600; }

.train-goal-ok {
    color: var(--success, #43b581);
    font-size: 12px;
    font-weight: 600;
}

.train-goal-table { margin-bottom: 0; }
.train-goal-table td { border-top: none !important; color: var(--text-dim); padding: 2px 0 !important; }
.train-goal-table td:last-child { text-align: right; }

/* Oppfylt delmål grønt: du skal kunne se hvilken av de to som mangler uten å
   lese tallene. */
.train-goal-done { color: var(--success, #43b581); }

.train-goal-warn {
    color: var(--danger, #ed4245);
    font-size: 12px;
    margin: var(--s2) 0 0;
}


/* ---------- fight club ----------
   Gjenbruker .train-score* og .train-goal-table fra treningssenteret: de to
   sidene viser samme slags tall og skal se like ut. Bare det som er eget for
   kamp står her. */

.fight-wins   { color: var(--success); }
.fight-losses { color: var(--danger); }

.fight-locked { text-align: center; }
.fight-locked p { color: var(--text-dim); }
.fight-locked-title { color: var(--text); font-weight: 600; }
.fight-locked-hint { color: var(--muted); font-size: 12px; }

/* Framdriftslinjen mot å slippe inn.
   Egne klassenavn, ikke .train-progress: den fantes i treningssenteret helt til
   divisjonene ble fjernet, og forsvant sammen med dem. Å gjenbruke et navn som
   ikke lenger er definert ga en usynlig boks -- teksten under sto der, men selve
   linjen hadde verken høyde eller farge.
   Bredden holdes igjen så den leser som en måler og ikke som en skillelinje
   tvers over panelet. */
.fight-progress {
    background-color: var(--surface-3);
    border-radius: 999px;
    height: 8px;
    margin: 0 auto;
    max-width: 320px;
    overflow: hidden;
}

.fight-progress-bar {
    background-color: var(--accent-hover);
    height: 100%;
    /* Synlig også helt i starten: 0 % er en tom stripe, men 1-2 % skal ikke være
       en usynlig flis. */
    min-width: 2px;
    transition: width 0.3s ease;
}

.fight-locked-percent { color: var(--muted); font-size: 12px; margin-top: var(--s2); }

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

.fight-board { margin-bottom: 0; }
.fight-board td, .fight-board th { padding: var(--s1) var(--s2) !important; }
.fight-board th { color: var(--muted); font-size: 12px; font-weight: 600; }
.fight-board td { color: var(--text-dim); }

/* Egen rad uthevet: en toppliste leses for å finne seg selv først. */
.fight-board-me td { background-color: var(--accent-weak); color: var(--text); }

/* Kampvalgene bærer tre linjer hver -- navn og odds, beskrivelse, og hva som
   står på spill -- så de er høyere enn treningens radioer og trenger en ramme
   for å lese som tre bokser i stedet for en vegg av tekst. */
.fight-option {
    align-items: flex-start;
    border: 1px solid var(--border-soft);
    border-radius: var(--radius-sm);
    cursor: pointer;
    display: flex;
    font-weight: 400;
    gap: var(--s3);
    margin: 0 0 var(--s2);
    padding: var(--s3);
}

.fight-option:hover { background-color: var(--surface-2); }

/* Valgt kamp markeres på hele boksen. Innsatsen her er liv, så det skal ikke gå
   an å trykke "Slåss" i tro om at man valgte gata. */
.fight-option:has(input:checked) {
    background-color: var(--accent-weak);
    border-color: var(--accent);
}

.fight-option input { margin: 4px 0 0; }

.fight-option-body { display: block; flex: 1 1 auto; min-width: 0; }

.fight-option-head {
    display: flex;
    gap: var(--s2);
    justify-content: space-between;
}

.fight-option-name { color: var(--text); font-weight: 600; }

/* Oddsen er det tallet man sammenligner mellom de tre, så den får aksentfargen
   og tabularsifre slik at kolonnen står rett. */
.fight-option-chance {
    color: var(--accent-hover);
    font-weight: 700;
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
    font-feature-settings: "tnum";
}

.fight-option-desc { color: var(--text-dim); display: block; font-size: 12px; margin-top: 2px; }
.fight-option-meta { color: var(--muted); display: block; font-size: 12px; margin-top: var(--s1); }

/* ---------- mobile ----------
   Keeps the stock .show-sidebar contract that js/mobile.js drives. */

@media (max-width: 991px) {

    html, body { font-size: 13px; height: 100%; }

    .layout { display: block; padding: 0 var(--s3) var(--s4); }

    .navbar-toggle { display: block; }

    /* Logo, clock and user do not fit side by side on a phone. The clock is the
       least useful of the three, so it goes; the rest is allowed to shrink. */
    .topbar-inner { gap: var(--s2); padding: var(--s2) var(--s3); }

    /* The banner keeps the same side padding as the topbar it hangs from, so
       the two stay aligned once the phone rules narrow it. */
    .announce { padding: var(--s2) var(--s3); }
    .topbar-logo img { max-height: 30px; }
    .topbar-clock { display: none; }

    /* The clock was the only flex: 1 1 auto item in the strip, so hiding it also
       took away the spring that held the bell and the player apart from the
       wordmark -- everything collapsed into a huddle on the left. The bell is
       the first of the right-hand group, so it carries the gap instead. */
    .topbar-bell { margin-left: auto; }

    /* The username is a link rendered by the userName partial, so the clamp has
       to reach the anchor inside -- clamping only the span lets it push wider. */
    .topbar-user { flex-shrink: 1; min-width: 0; }
    .topbar-user-toggle { max-width: 45vw; }

    .topbar-name,
    .topbar-name a {
        display: block;
        max-width: 100%;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
    }

    /* Both sidebars fold away behind the toggle, and both come back together --
       the stock .show-sidebar contract that js/mobile.js drives. */
    .side-bar { display: none; width: 100%; }

    .show-sidebar .side-bar { display: block; }

    .show-sidebar .game-container { display: none; }

    .game-container { width: 100%; }

    .side-bar .list-group .list-group-item { font-size: 14px; line-height: 24px; padding: 10px var(--s3); }

    .crime-holder { padding: var(--s3); }

    .crime-holder .commit { display: inline-block; float: none; margin: var(--s2) 0 0; }

    .login-form { max-width: none; padding: var(--s4); }

    /* Wide tables must scroll inside their own box, never the page. */
    .table-responsive { -webkit-overflow-scrolling: touch; border: none; overflow-x: auto; }

    /* A Bootstrap .row carries -15px side margins that a .container's padding is
       meant to cancel out. The game column is not a container, so the row hung
       15px past both screen edges and the whole page could be dragged sideways.
       Stacked one per line on a phone, the gutters have nothing left to space
       out, so the padding goes too and the row lines up with the panels above
       it. */
    .game-container .row { margin-left: 0; margin-right: 0; }
    .game-container .row > [class*="col-"] { padding-left: 0; padding-right: 0; }
}

/* ---------- phones ---------- */

/*
 * The rules above were written for a tablet. On a phone the topbar still ran
 * off the screen: the wordmark is roughly 9:1, so capping only its HEIGHT at
 * 30px still left it 269px wide -- two thirds of a 402px screen -- and
 * .topbar-logo is flex: 0 0 auto, so it could not give any of that back. The
 * bell and the player name were pushed off the right edge with no way to reach
 * them. Cap the WIDTH and let the height follow.
 */
@media (max-width: 600px) {

    .topbar-logo { flex: 0 1 auto; min-width: 0; }
    .topbar-logo img { max-height: 26px; max-width: 38vw; }

    /* A flex item defaults to min-width: auto, which refuses to shrink below
       its content -- the reason the name kept the row wider than the screen.
       Every text-bearing box in the strip needs an explicit floor of 0. */
    .topbar-user { min-width: 0; }
    .topbar-user-toggle { max-width: none; min-width: 0; padding: var(--s1); }
    .topbar-user-meta { min-width: 0; overflow: hidden; }

    .topbar-rank {
        display: block;
        max-width: 100%;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
    }

    .topbar-avatar { height: 30px; width: 30px; }
}

/* Small phones: the rank is the least important thing in the bar, and giving
   its width to the name is a better trade than truncating both. */
@media (max-width: 380px) {
    .topbar-logo img { max-width: 34vw; }
    .topbar-rank { display: none; }
}
