.page {
    display: block;
    position: relative;
    width: 190mm;
    height: 277mm;
}

@media print {
    * {
        background: transparent;
    }

    @page {
        size: 21cm 29.7cm;
        margin-top: 10mm;
        margin-right: 10mm;
        margin-left: 10mm;
        margin-bottom: 10mm;
    }

    .pageContent {
        width: 100%;
        height: 100%;
    }

    .pagebreak {
        display: block;
        page-break-before: always;
    }

    .no-print {
        display: none;
    }
}

/* settings-preview dialog used for building, tree */
.settings-preview-dialog {
    display: flex;
    flex-direction: row;
    height: 100%;
    overflow: hidden;
}

.settings-preview-dialog .settings {
    flex: 0 0 auto;
    overflow: auto;
    border: 1px solid var(--separator-color);
}

.settings-preview-dialog .preview {
    flex: 1 1 auto;
    min-width: 200px;
    min-height: 200px;
    position: relative;
    border: 1px solid var(--separator-color);
}

.texture-select {
    max-height: 80vh;
}

.texture-select fieldset {
    max-height: 70vh;
    padding-bottom: 10px;
    overflow: hidden;
}

.texture-select fieldset > div {
    height: 100%;
    overflow: auto;
}

.texture-list-entry {
    cursor: pointer;
}

body:not(.no-hover) .texture-list-entry:hover {
    background-color: #ff0;
}

.raily-free-tier-limit-warning {
    display: flex;
    flex-direction: row;
    align-items: center;
    gap: 8px;
    background: #fff1d6;
    border: 1px solid #f2b84d;
    color: #8a4b00;
    padding: 6px 10px;
    margin: 0 4px 4px 4px;
    border-radius: 4px;
}

.raily-free-tier-limit-warning-icon {
    color: #d88200;
}

.raily-free-tier-limit-warning-text {
    font-size: 13px;
    line-height: 1.3;
}

.left-tool-panel {
    display: inline-flex;
    flex-flow: row;
    overflow: hidden;
    width: min-content;
    border-right: 1px solid var(--separator-color);
}

.raily-left-tools {
    flex: 0 0 200px;
    min-width: 200px;
    display: flex;
    flex-flow: column;
    overflow-y: auto;
    overflow-x: hidden;
}

.vertical-left-toolbar {
    display: flex;
    flex-flow: column;
    width: calc(10 + var(--button-size));
    overflow-y: auto;
    overflow-x: hidden;
    border-left: 1px solid var(--separator-color);
}

.editor {
    flex: 1;
    position: relative;
    height: 100%;
    min-width: 50px;
    min-height: 50px;
}

.right-tool-panel {
    flex: 0 0 200px;
    display: flex;
    flex-direction: column;
    overflow: hidden;
    height: 100%;
    min-height: 0;
    border-left: 1px solid var(--separator-color);
}

.right-tool-panel > .tab-container {
    flex: 1 1 auto;
    min-height: 0;
    width: 100%;
}

.right-tool-panel .tab-content {
    display: flex;
    flex-direction: column;
    overflow: hidden;
    min-height: 0;
}

.right-tool-panel .train-tab {
    height: 100%;
    min-height: 0;
    overflow: hidden;
}

.right-tool-panel .train-repository-list,
.right-tool-panel .train-panel .train-list {
    min-height: 0;
    overflow-y: auto;
    overflow-x: hidden;
}

.right-tool-panel .train-panel {
    min-height: 0;
    overflow: hidden;
}

.footer {
    flex: 0 0 auto;
    background: var(--main-menu-bar-background-color);
    border-top: 1px solid var(--separator-color);
    height: 44px;
    line-height: 14px;
    font-size: 14px;
}


.short-context-help {
    background-color: var(--context-help-background-color);
    color: var(--context-help-foreground-color);
    height: 100%;
}

.status-footer-content {
    align-items: stretch;
    gap: 8px;
    /* Footer must host two-line blocks; let children fill the height. */
    height: 100%;
    /* Reserve space on the right edge for the floating (position:fixed)
       feedback button so the rightmost status info doesn't slide under it.
       left-content-right sets width:100%, so without border-box this padding is
       added to that width instead of taken out of it -- the box grows past the
       footer and the reservation buys nothing. */
    box-sizing: border-box;
    padding-right: 8em;
}

.status-footer-content .left {
    align-items: center;
    justify-content: center;
    overflow: hidden;
}

.status-footer-content .content {
    /* Spacer flexes to push the right zone to the edge. */
    min-width: 0;
}

/* Center zone: keeps the working-task pill centred in the footer. */
.status-footer-center {
    align-items: center;
    justify-content: center;
    min-width: 0;
}

.status-footer-right {
    align-items: center;
    gap: 8px;
}

/* Left zone: name (top) / modified (bottom) when idle; context help when editing. */
.name-modified-panel {
    justify-content: center;
    gap: 0;
}

.name-modified-panel label {
    /* Make the name look like a heading line. */
    font-size: 14px;
    font-weight: 700;
    line-height: 18px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 22em;
}

.name-modified-panel .name-row {
    align-items: center;
    gap: 4px;
}

.name-modified-panel label.renamable {
    cursor: pointer;
}

/* The rename button appears on hover, the way the file dialogs offer their per-row actions — and on
   keyboard focus, which is the only way to reach it without a pointer.
   Hidden by opacity, not by visibility or display: those two take the button out of the tab order, so
   the focus rule below could never fire and there would be no keyboard path to renaming at all. It
   keeps its box either way, so the name does not shift sideways when it appears, and pointer-events
   are off while invisible so the gap beside the name is not a click target nobody can see. */
.name-modified-panel .rename-plan {
    opacity: 0;
    pointer-events: none;
    flex: 0 0 auto;
}

.name-modified-panel .name-row:hover .rename-plan,
.name-modified-panel .name-row:focus-within .rename-plan {
    opacity: 1;
    pointer-events: auto;
}

.name-modified-panel > .modified {
    font-size: 11px;
    line-height: 14px;
    color: var(--context-help-foreground-color);
}

/* Save-state badge: a plain colour-coded pill so the working state is obvious
   at a glance — orange when there are unsaved changes, blue once saved. */
.save-state {
    display: inline-flex;
    align-items: center;
    padding: 2px 10px;
    border-radius: 10px;
    font-size: 11px;
    font-weight: 600;
    line-height: 14px;
    white-space: nowrap;
    color: #fff;
}

/* Dark text on the amber, not white: white on this orange is 2.7:1, which is under the 4.5:1 that
   11px text needs to be read at a glance. Near-black brown keeps the badge amber and reaches 6.2:1. */
.save-state.modified {
    background: #e8842f;
    color: #2b1a00;
}

.save-state.saved {
    background: #3d6fd6;
}

/* Context help (shown instead of name/modified while editing). */
.top-content-bottom.left > div,
.status-footer-content .left .left-content-right {
    align-items: center;
}

/* Position info: vertical — coordinates on top, element-info string below. */
.position-info {
    width: 14em;
    justify-content: center;
}

.position-info-coord {
    font-size: 12px;
    line-height: 16px;
    white-space: nowrap;
    color: var(--context-help-foreground-color);
}

.position-info-element {
    font-size: 11px;
    line-height: 14px;
    white-space: nowrap;
    color: var(--context-help-foreground-color);
    opacity: 0.8;
}

/* Working-task pill: prominent so pending background work (CSG, meshing …) is
   obvious. Accent background with a white wave animation. */
.work-status {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 3px 12px 3px 10px;
    border-radius: 14px;
    background: #3d6fd6;
    color: #fff;
    box-shadow: 0 0 8px rgba(61, 111, 214, 0.6);
    width: auto;
}

.work-status > :first-child {
    flex-shrink: 0;
}

.work-status-text {
    font-size: 12px;
    font-weight: 700;
    white-space: nowrap;
    color: #fff;
}

.floating-feedback {
    position: fixed;
    /* Above dialogs (10000) and teaching bubbles (10001) so the button stays
       visible and is captured in feedback screenshots. */
    z-index: 10002;
    bottom: 6px;
    right: 10px;
    cursor: pointer;
    font-size: 12px;
    color: var(--link-color);
    text-decoration: underline;
    white-space: nowrap;
    background: rgba(0, 0, 0, 0.25);
    padding: 4px 8px;
    border-radius: 4px;
}

body:not(.no-hover) .floating-feedback:hover {
    opacity: 0.7;
}

.expand-handle {
    display: flex;
    height: 27px;
    width: 27px;
    bottom: 30px;
    background-color: rgba(0, 0, 255, 0.55);
    align-content: center;
    justify-content: center;
    position: absolute;
    overflow: hidden;
    cursor: pointer;
}

.expand-handle > div {
    color: white;
}

.expand-handle.left {
    right: 0;
}

.expand-handle.right {
    left: 0;
}

@media screen and (max-width: 600px) {
    #tools {
        display: none;
    }
}

#shortcuts {
    flex: 0 0 auto;
}

body:not(.no-hover) .scene-graph-entry-header:hover {
    background-color: var(--default-hover-background-color);
    color: var(--default-hover-foreground-color);
    cursor: pointer;
}

.hintPanelWrap {
    left: 50%;
    top: 10%;
    position: absolute;
}

.hintPanel {
    left: -50%;
    padding: 8px;
    border: 1px solid #888;
    opacity: 0.5;
    background-color: #fff;
    border-radius: 8px;
    position: relative;
}

.controls {
    position: absolute;
    top: 20px;
    right: 20px;
    border: 1px solid var(--separator-color);
    opacity: 0.5;
    background-color: rgba(255, 255, 255, 0.4);
    border-radius: 5px;
}

.view-mode-overlay {
    display: flex;
    flex-direction: column;
}

.view-mode-button-row {
    display: flex;
}

.view-mode-release-info {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    border-top: 1px solid var(--separator-color);
    padding: 3px 6px 4px;
}

.view-mode-release-tag {
    border-radius: 999px;
    font-size: 11px;
    padding: 1px 7px;
    font-weight: 700;
    color: #fff;
}

.view-mode-release-tag.alpha {
    background-color: #c62828;
}

.view-mode-release-tag.beta {
    background-color: #1565c0;
}

.view-mode-release-info-icon {
    opacity: 0.85;
}

.drag-image {
    position: absolute;
    pointer-events: none;
    z-index: 1000;
}

.bubble {
    position: absolute;
    background-color: var(--dialog-background-color);
    border: 2px solid var(--separator-color);
    color: var(--default-foreground-color);
    border-radius: 5px;
    box-shadow: rgba(0, 0, 0, 0.3) 2px 2px 2px;
    display: inline-block;
    padding: 18px 18px;
    vertical-align: top;
    left: 100px;
    top: 100px;
    z-index: 10000;
}

.bubble.bottom:before {
    content: " ";
    position: absolute;
    box-shadow: rgba(0, 0, 0, 0.3) 2px 2px 2px;
    transform: rotate(45deg);
    bottom: -10.5px;
    left: 37px;
    width: 17px;
    height: 17px;
    background-color: var(--dialog-background-color);
    border-width: 2px;
    border-style: solid;
    border-color: transparent var(--separator-color) var(--separator-color) transparent;
}

.bubble.top:before {
    content: " ";
    position: absolute;
    transform: rotate(-135deg);
    top: -10.5px;
    left: 37px;
    width: 17px;
    height: 17px;
    background-color: var(--dialog-background-color);
    border-width: 2px;
    border-style: solid;
    border-color: transparent var(--separator-color) var(--separator-color) transparent;
}

.repository-list-entry {
    display: flex;
    justify-content: center;
    align-items: center;
    flex-direction: row;
    border: 1px solid var(--separator-color);
}

.drag-handle {
    height: 100%;
    width: 30px;
    display: flex;
    justify-content: center;
    align-items: center;
    background-color: var(--secondary-button-background-color);
}

.grip {
    width: 20px;
    height: 8px;
    background-image: radial-gradient(black 40%, transparent 40%);
    background-size: 4px 4px;
    background-color: var(--secondary-button-hover-background-color);
    border: 1px solid var(--separator-color);
    pointer-events: none;
}

.element-name-title {
    font-weight: 700;
}

/* Train composition editor (instrument panel): horizontal strip of wagon cards and coupler chips. */
.train-composition-panel {
    display: flex;
    flex-direction: row;
    flex-wrap: nowrap;
    overflow-x: auto;
    overflow-y: hidden;
    align-items: center;
    gap: 4px;
    padding: 4px 8px;
}

.train-wagon-card {
    border: 1px solid var(--dialog-border-color);
    border-radius: 4px;
    padding: 6px 8px;
    min-width: 96px;
    background: var(--panel-background-color);
    align-items: center;
    flex-shrink: 0;
    gap: 4px;
}

.train-card-title {
    font-weight: 700;
    white-space: nowrap;
}

.train-card-info {
    font-size: 10px;
    color: var(--disabled-foreground-color);
    white-space: nowrap;
}

.train-card-row {
    gap: 4px;
    align-items: center;
}

.train-coupler-chip {
    align-items: center;
    flex-shrink: 0;
    gap: 2px;
}

/* Train control panel: the switch-ahead widget and the compact speed input. */
.train-panel .train-switch-button {
    width: 52px;
    height: 52px;
    flex-shrink: 0;
}

/* Fixed height whether empty or showing a switch: appearing content must not shift the card. */
.train-panel .train-switch-row {
    height: 56px;
    flex-shrink: 0;
    justify-content: center;
}


/* Fullscreen cockpit bar: the driving controls along the bottom while riding a train. */
.cockpit-bar {
    position: fixed;
    left: 50%;
    bottom: 0;
    transform: translateX(-50%);
    align-items: center;
    gap: 20px;
    padding: 10px 28px 6px 28px;
    background: var(--panel-background-color);
    border: 1px solid var(--dialog-border-color);
    border-bottom: none;
    border-radius: 14px 14px 0 0;
    box-shadow: 0 -2px 14px rgba(0, 0, 0, 0.35);
    z-index: 500;
    width: auto;
}

.cockpit-bar .cockpit-speed-digits {
    font-size: 22px;
    font-weight: 700;
    min-width: 110px;
    text-align: center;
    font-variant-numeric: tabular-nums;
}

.cockpit-bar .cockpit-reverse {
    font-size: 14px;
    font-weight: 700;
    color: var(--primary-color, #e33);
}

.cockpit-bar .cockpit-switch-button,
.cockpit-bar .cockpit-stop-button {
    width: 72px;
    height: 72px;
    flex-shrink: 0;
}

/* Who is driving, as a word: at a glance among the icons, the only readable way to say which of two
   modes is active. Sized to the other cockpit buttons so the bar stays even. */
.cockpit-bar .cockpit-mode-button {
    width: 72px;
    height: 72px;
    flex-shrink: 0;
    font-weight: bold;
    font-size: 0.8em;
}

/* The simulation clock stacks its date over its time (see makeSimClockDisplay): a toolbar's horizontal
   space is shared with every button on it, and a date is nearly twice as wide as the time it qualifies. */
.sim-clock-display {
    white-space: pre-line;
    line-height: 1.1;
    text-align: center;
}

/* Trader information, shown in the status bar's centre while nothing is being
   worked on. Deliberately quiet: it has to be reachable, not noticed. */
/* One line, always. The links row is a flex item that would otherwise take the
   full width and push the close button onto a second line -- which made the bar
   taller than the footer and left the text sitting above the pointer position
   instead of beside it. Narrow screens get the compact form, not a wrap. */
.raily-legal-notice {
    display: flex;
    flex-wrap: nowrap;
    align-items: center;
    gap: 12px;
    font-size: 12px;
    line-height: 16px;
    opacity: 0.65;
}

body:not(.no-hover) .raily-legal-notice:hover {
    opacity: 1;
}

.raily-legal-notice-full {
    display: flex;
    flex-wrap: nowrap;
    align-items: center;
    flex: 0 1 auto;
    min-width: 0;
    /* Without this the nowrap row keeps its full width and simply paints past
       the container -- straight over the close button sitting after it. */
    overflow: hidden;
    gap: 12px;
}

/* basic.css sets "label { font-size: smaller }", which shrank these to ~9px
   against the 11px around them. Stated outright, and matched to the pointer
   position across the footer so the two read as one row. */
.raily-legal-notice-link,
.raily-legal-notice-full > label {
    font-size: 12px;
    line-height: 16px;
}

.raily-legal-notice-link {
    flex: 0 0 auto;
    width: auto;
    white-space: nowrap;
    text-decoration: underline;
    cursor: pointer;
}

/* One entry instead of a sentence and four links once the footer is too narrow
   to hold them on one line. The threshold is where the full form starts to
   wrap, not a device class. */
.raily-legal-notice-compact {
    display: none;
}

@media (max-width: 900px) {
    .raily-legal-notice-full {
        display: none;
    }

    .raily-legal-notice-compact {
        display: inline;
    }
}

/* The dialog is the document itself, so it gets room to be read. */
.raily-legal-dialog {
    width: 100%;
    height: 100%;
    min-height: 60vh;
}

/* Never shrinks and never gets overlapped: it is the only way to dismiss the
   bar, so it keeps its box whatever the links do. */
.raily-legal-notice-close {
    flex: 0 0 auto;
    transform: scale(0.7);
    z-index: 1;
}

/* Sits at the end of the warning strip, so the sentence reads first and the
   offer is where the eye already is. */
.raily-free-tier-limit-warning-buy {
    flex: 0 0 auto;
    margin-left: auto;
}

/* The unlicensed mark. Bottom-right, above the footer strip and clear of the
   feedback link, faint enough to read past while planning. It is meant to be
   present, not consulted. */
.raily-watermark {
    position: fixed;
    /* Below .eni-modal (100), which is where dialogs actually live -- the
       comment on .floating-feedback claiming 10000 does not describe them. The
       mark belongs on the plan, so anything the user opened covers it. */
    z-index: 50;
    right: 12px;
    bottom: 58px;
    /* FlexPanel.vertical brings top-content-bottom, which is 100% x 100%. Fixed
       positioning turns that into a full-screen box that happens to look right
       only because the text sits at its top. */
    width: max-content;
    height: auto;
    max-width: 15em;
    padding: 5px 9px;
    border-radius: 4px;
    /* Light theme: a pale wash over the plan, dark text. Stated rather than
       inherited, because the mark sits on the drawing and not on a panel, so
       the panel variables are the wrong reference. */
    background: rgba(255, 255, 255, 0.62);
    color: #303030;
    cursor: pointer;
    opacity: 0.55;
    transition: opacity 0.4s ease;
    pointer-events: auto;
}

/* On a dark plan the same wash inverts; a translucent black box on a dark
   background was legible but muddy. */
@media (prefers-color-scheme: dark) {
    .raily-watermark {
        background: rgba(20, 20, 20, 0.62);
        color: #e6e6e6;
    }
}

:root[data-force-theme="dark"] .raily-watermark {
    background: rgba(20, 20, 20, 0.62);
    color: #e6e6e6;
}

:root[data-force-theme="light"] .raily-watermark {
    background: rgba(255, 255, 255, 0.62);
    color: #303030;
}

body:not(.no-hover) .raily-watermark:hover {
    opacity: 0.95;
}

.raily-watermark-title {
    font-size: 12px;
    line-height: 16px;
    font-weight: 600;
    white-space: nowrap;
}

.raily-watermark-usage {
    font-size: 11px;
    line-height: 14px;
}

/* One slow swell every half hour. Opacity only: moving or resizing it would
   pull the eye off the plan, which is the thing the user is actually doing. */
@keyframes raily-watermark-pulse {
    0%   { opacity: 0.55; }
    50%  { opacity: 1; }
    100% { opacity: 0.55; }
}

.raily-watermark-pulse {
    animation: raily-watermark-pulse 4s ease-in-out;
}

/* No animation for anyone who has asked the system for less motion. */
@media (prefers-reduced-motion: reduce) {
    .raily-watermark-pulse {
        animation: none;
    }
}

/* The mesh-cache trade at the foot of the save dialog. Quiet, and absent
   entirely on a plan where it would save nothing worth mentioning. */
.raily-save-cache {
    gap: 2px;
    padding: 6px 4px 2px 4px;
}

.raily-save-cache-detail {
    font-size: 12px;
    opacity: 0.75;
    padding-left: 26px;
}

/* Qualifying notes in the buy dialog: what a subscription leaves behind, and
   what a one-off purchase does not cover. Quieter than the offer itself, but
   deliberately not hidden. */
.raily-buy-note {
    font-size: 12px;
    line-height: 1.35;
    opacity: 0.8;
    padding: 2px 0 6px 0;
}
