/*
 * g60printer.css
 * Google60-style line printer for PDP-11 console output
 * Adapted from Google60 by Norbert Landsteiner (mass:werk)
 */

/* Font face declaration for the LP1 font */
@font-face {
    font-family: 'lp1_regular';
    src: url('../assets/fonts/lp1/lp1-regular-webfont.eot');
    src: url('../assets/fonts/lp1/lp1-regular-webfont.eot#iefix') format('embedded-opentype'),
        url('../assets/fonts/lp1/lp1-regular-webfont.woff') format('woff'),
        url('../assets/fonts/lp1/lp1-regular-webfont.ttf') format('truetype'),
        url('../assets/fonts/lp1/lp1-regular-webfont.svg#lp1_regular') format('svg');
    font-weight: normal;
    font-style: normal;
}

/* Printer container – replaces the old console textarea */
#g60printer {
    position: relative;
    /* Width reduced by 2 × #printer_right (2 × 66px = 132px) to slim the
       printer body and match the narrower keyboard deck. */
    width: 808px;
    height: 380px;
    /* Sand-beige ASR33 body (Model 33 ASR cabinet tone) instead of the dark
       Google60 machine. The base sand #d1b48c is the shared cabinet colour;
       the lighter/darker shades below are derived from it. */
    background-color: #d1b48c;
    overflow: hidden;
    border: 1px solid #a68c66;
    border-radius: 12px 12px 4px 4px;
    box-shadow: 0 8px 18px rgba(0, 0, 0, 0.35), inset 0 1px 0 rgba(255, 255, 255, 0.65);
    margin: 8px 0;
}

#g60printer div#printer {
    position: absolute;
    top: 0;
    left: 0;
    width: 808px;
    height: 374px;
    background: linear-gradient(180deg, #e3cdaa 0%, #d8bd98 45%, #c6a87e 100%);
    /* Round the top corners to match the #g60printer body radius. */
    border-radius: 12px 12px 0 0;
}

/* Black paper slot: the sheet emerges through a dark horizontal slit. Its
   BOTTOM edge sits at the top of the lower face plate (305px) and its
   vertical centre lands on the paper's bottom edge (the carriage line at
   316px), so the paper appears to come out of the MIDDLE of the slot. The
   slot is drawn above the face plate but below the paper, so the rising
   sheet passes in front of its upper half. */
#g60printer div#printer::after {
    content: "";
    position: absolute;
    left: 67px;
    /* Ends exactly where the right skin starts (742px − 67px = 675px), so the
       slot never runs under the side skin — same seam as the lower face plate. */
    width: 675px;
    top: 305px;
    height: 22px;
    background: #0a0a0a;
    border-top: 1px solid #3a3a3a;
    border-bottom: 1px solid #3a3a3a;
    border-radius: 2px;
    box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.9);
    z-index: 3;
    pointer-events: none;
}

#g60printer #printheadarea {
    display: block;
    position: absolute;
    top: 298px;
    left: 67px;
    width: 741px;
    max-width: 741px;
    height: 30px;
    max-height: 30px;
    padding: 0;
    margin: 0;
    z-index: 5;
    overflow: hidden;
}

#g60printer #printhead {
    display: block;
    position: absolute;
    top: 0;
    left: 16px;
    padding: 0;
    margin: 0;
}

#g60printer div#printer_frontpannel {
    position: absolute;
    top: 305px;
    left: 67px;
    /* Ends exactly where the right skin starts (742px − 67px = 675px), so
       the lower face plate meets the side skin in a clean seam instead of
       tucking under it. */
    width: 675px;
    height: 69px;
    /* Sand lower face plate (no Google60 bitmap skin). */
    background: linear-gradient(180deg, #d2b78f 0%, #b89b71 100%);
    border-top: 1px solid #a68c66;
    border-radius: 0 0 8px 8px;
    z-index: 2;
}

#g60printer div#printer_left {
    position: absolute;
    top: 0;
    left: 0;
    width: 67px;
    height: 374px;
    background: linear-gradient(90deg, #b89b71 0%, #d1b48c 100%);
    border-right: 1px solid #a68c66;
    /* Round the top-left corner to match the #g60printer body radius. */
    border-radius: 12px 0 0 0;
}

#g60printer div#printer_right {
    position: absolute;
    top: 0;
    left: 742px;
    width: 66px;
    height: 374px;
    background: linear-gradient(270deg, #b89b71 0%, #d1b48c 100%);
    border-left: 1px solid #a68c66;
    /* Round the top-right corner to match the #g60printer body radius. */
    border-radius: 0 12px 0 0;
}

/* Model 33 ASR paper roll, poking out of the top of the body. Drawn BEHIND
   the rising sheet (z-index 0, below #paper's 1): while the paper is still low
   the roll is visible as a dome above it, and as the sheet grows upward it
   passes OVER the roll and closes over it — so the sheet is never interrupted
   by the roll (a roll in front, z-index 4, would cut the sheet with a break). */
#g60printer::before {
    content: "";
    position: absolute;
    left: 50%;
    margin-left: -160px;
    top: -32px;
    width: 320px;
    height: 40px;
    /* Top cover dome with two rounded corners: part of the cabinet, so it
       shares the sand-beige body tone (the sheet rising over it stays paper). */
    border-radius: 40px 40px 0 0;
    background: linear-gradient(180deg, #e3cdaa 0%, #d6bb95 60%, #c6a87e 100%);
    border: 1px solid #a68c66;
    border-bottom: none;
    box-shadow: inset 0 4px 8px rgba(0, 0, 0, 0.18), 0 -2px 6px rgba(0, 0, 0, 0.15);
    z-index: 0;
    pointer-events: none;
}

/* Carriage observation window: a real Model 33 ASR has a glass window through
   which the operator sees the print head advance. A translucent pane sits right
   above the carriage so the print head (z-index 3) stays visible underneath. */
#g60printer::after {
    content: "";
    position: absolute;
    left: 67px;
    right: 67px;
    bottom: 64px;
    height: 44px;
    border: 2px solid rgba(176, 168, 144, 0.55);
    border-radius: 5px;
    background: linear-gradient(180deg, rgba(255, 255, 255, 0.22) 0%, rgba(255, 255, 255, 0.05) 45%, rgba(140, 128, 104, 0.12) 100%);
    box-shadow: inset 0 2px 8px rgba(0, 0, 0, 0.18), 0 1px 0 rgba(255, 255, 255, 0.5);
    z-index: 6;
    pointer-events: none;
}

/* Brand plate on the lower face plate: a real Model 33 ASR carries the
   Teletype Corporation wordmark (lightning-bolt emblem + TELETYPE) stamped
   on the cabinet, NOT a "MODEL 33 ASR" text label — matching historical
   photos. The wordmark is drawn from assets/images/teletype-corp-logo.svg. */
#g60printer div#printer_frontpannel::after {
    content: "";
    position: absolute;
    left: 14px;
    top: 57%;
    transform: translateY(-50%);
    width: 60px;
    height: 24px;
    background-image: url('../assets/images/teletype-corp-logo.svg');
    background-repeat: no-repeat;
    background-size: contain;
    background-position: left center;
    pointer-events: none;
}

#g60printer div#paper {
    position: absolute;
    top: 0;
    left: 67px;
    width: 741px;
    height: 400px;
    max-height: 400px;
    vertical-align: top;
    text-align: left;
    padding: 0;
    margin: 0;
    /* Above the paper slot and the lower face plate so the rising sheet
       visibly passes in front of them, but below the print head and the
       carriage window. */
    z-index: 4;
}

#g60printer div#paper.paperNoScroll {
    overflow: hidden;
}

#g60printer div#paper.paperScroll {
    overflow-y: auto;
    overflow-x: hidden;
}

#g60printer div#paper_topspacer {
    position: relative;
    height: 345px;
    width: 1px;
    margin: 0;
    padding: 0;
}

#g60printer div#paper_topspacer.paperScroll {
    height: 16px;
}

#g60printer table#paper_area {
    margin: 0;
    padding: 0;
    border: 0 none;
    border-collapse: collapse;
    border-spacing: 0;
}

#g60printer table#paper_area td {
    vertical-align: top;
    margin: 0;
    white-space: nowrap;
}

#g60printer td#papermargin_left,
#g60printer td#papermargin_right {
    background-image: url('../assets/images/paper-margin.png');
    background-repeat: repeat-y;
    width: 33px;
    min-width: 33px;
}

#g60printer td#papermargin_left {
    background-position: -3px 0;
}

#g60printer td#papermargin_right {
    background-position: 0 0;
}

#g60printer td#paper_top {
    background-image: url('../assets/images/paper-edge.png');
    background-repeat: repeat-x;
    background-position: 0 0;
    height: 5px;
}

#g60printer tr#paper_bottom {
    background-image: url('../assets/images/paper-edge.png');
    background-repeat: repeat-x;
    background-position: 0 -5px;
    height: 5px;
    display: none;
}

#g60printer td#paper_printarea {
    width: 705px;
    color: #36363c;
    font-size: 13px;
    text-align: left;
    font-family: lp1_regular, "Trebuchet MS", sans-serif;
    font-style: normal;
    font-weight: 400;
    line-height: 16px;
    background-color: white;
    padding: 57px 18px 1px 18px;
    white-space: nowrap;
    background-image: url('../assets/images/paper.png');
    background-repeat: repeat;
    -webkit-text-shadow: 0 0 1px rgba(115, 115, 121, 0.6), 0 0 2px rgba(115, 115, 121, 0.3);
    -moz-text-shadow: 0 0 1px rgba(115, 115, 121, 0.6), 0 0 2px rgba(115, 115, 121, 0.3);
    -o-text-shadow: 0 0 1px rgba(115, 115, 121, 0.6), 0 0 2px rgba(115, 115, 121, 0.3);
    text-shadow: 0 0 1px rgba(115, 115, 121, 0.6), 0 0 2px rgba(115, 115, 121, 0.3);
    -webkit-font-smoothing: subpixel-antialiased;
}

#g60printer td#paper_printarea span {
    display: inline-block;
    vertical-align: top;
    white-space: pre;
    width: 7px;
    max-width: 7px;
    height: 16px;
    max-height: 16px;
    text-align: center;
}

/* Right-margin overstrike: characters printed after the carriage reached
   the last column pile up on top of each other, forming an unreadable
   dark blob (authentic Model 33 ASR behaviour). */
#g60printer td#paper_printarea span.overstrike {
    background-color: #3a3a3a;
    color: #8a8a8a;
    text-shadow: none;
}

/* Bold / underline emphasis produced by nroff/man overstrike (same glyph
   re-printed → bold; letter printed over an underscore → underline). */
#g60printer td#paper_printarea span.bold {
    font-weight: bold;
}

#g60printer td#paper_printarea span.underline {
    text-decoration: underline;
}

#g60printer td#paper_printarea span.drop {
    margin-top: 1px;
    height: 15px;
    max-height: 15px;
    overflow: hidden;
    text-shadow: 0 -1px 1px rgba(115, 115, 121, 0.7), 0 -1px 2px rgba(115, 115, 121, 0.4);
}

#g60printer td#paper_printarea span.shift {
    margin-top: -1px;
    text-shadow: 0 1px 1px rgba(115, 115, 121, 0.7), 0 1px 2px rgba(115, 115, 121, 0.4);
}

#g60printer td#paper_printarea span.nonAscii {
    font-size: 12px !important;
    line-height: 18px !important;
}

#g60printer td#paper_printarea p {
    margin: 0;
    padding: 0;
    max-height: 16px;
    vertical-align: top;
    white-space: nowrap;
    overflow: visible;
}

/* Form-feed page separator: 2.11BSD lpd sends FF between print jobs and the
   printer ejects to the top of the next page. The fold/perforation marker is
   a dashed seam across the full printable width. The Model 33 ASR console teletype
   disables the marker (smooth paper roll) and only advances the paper. */
#g60printer td#paper_printarea p.pageBreak,
#lp11_printer td#lp11g60paper_printarea p.pageBreak {
    margin: 0;
    padding: 0;
    max-height: 16px;
    border-bottom: 1px dashed #8a8a8a;
}

#g60printer div#printer_topoverlay,
#g60printer div#paper_topshadow {
    position: absolute;
    top: 0;
    left: 67px;
    width: 807px;
    height: 20px;
    padding: 0;
    margin: 0;
    background-image: url('../assets/images/paper-topoverlay.png');
    background-repeat: repeat-x;
}

#g60printer div#printer_topoverlay {
    z-index: 1;
}

#g60printer div#paper_topshadow {
    background-position: 0 -21px;
    z-index: 10;
}

/* ==================================================================
   Model 33 ASR console teletype — smooth plain paper (no tractor feed).
   A real Model 33 ASR was fed by friction with a smooth roll of paper, NOT
   the striped fanfold with sprocket holes used by line printers. The
   striped texture (paper.png) and the tractor-hole margins
   (paper-margin.png) are shared with the LP11 line printer, so here
   they are overridden with CSS gradients scoped ONLY to the teletype
   container #g60printer. The LP11 page (#lp11_printer) keeps the
   authentic fanfold look untouched.
   ================================================================== */
#g60printer td#paper_printarea {
    background: linear-gradient(to bottom, #f6f1e5 0%, #ede6d5 100%) repeat;
}

#g60printer td#papermargin_left,
#g60printer td#papermargin_right {
    /* The `background` shorthand resets image + repeat + position + color
       in one declaration, so no trace of paper-margin.png (sprocket holes)
       can survive here. The LP11 page rules below still use that image. */
    background: linear-gradient(to bottom, #f6f1e5 0%, #ede6d5 100%) repeat-y;
}

/* ==================================================================
   Model 33 ASR console keyboard — historical Teletype layout
   Placed below the paper printer on the console page. Round DARK
   keycaps with light legends on a cream deck, as on a real Model 33.
   ================================================================== */

#punchkeypane {
    position: relative;
    /* Same slim width as the printer (940px − 2 × 66px). */
    width: 808px;
    height: 240px;
    /* Sand ASR33 deck (no dark keyboardbg.jpg texture). The deck sits
       directly under the (now lowered) printer body — no gap between them. */
    background: linear-gradient(180deg, #d6bd99 0%, #bfa67e 100%);
    margin: 0;
    padding: 0;
    border: 1px solid #a68c66;
    border-top: none;
    border-radius: 0 0 12px 12px;
    box-shadow: inset 0 10px 16px rgba(0, 0, 0, 0.16);
}

#punchkeyboard {
    position: absolute;
    top: 14px;
    /* Shifted left so the rightmost keys — including BREAK in the middle row —
       clear the CCU apron (LINE/OFF/LOCAL) on the right side of the deck. */
    left: 70px;
}

/* ---- Round keycaps (diameter 36px, pitch 40px) ---- */

#punchkeyboard .m33-key {
    position: absolute;
    width: 36px;
    height: 36px;
    border-radius: 50%;
    box-sizing: border-box;
    cursor: default;
    user-select: none;
    /* Cylindrical key with a FLAT circular top: the solid dark base shadow
       (0 4px 0) reads as the keycap's side wall, and the light hit at 35% 35%
       gives the flat top its subtle dome. All caps are DARK plastic (like a
       real Model 33) with light printed legends. */
    background: radial-gradient(circle at 35% 35%, #6e6458 0%, #403830 100%);
    border: none;
    box-shadow:
        0 4px 0 #241f1a,
        0 6px 10px rgba(0, 0, 0, 0.5);
}

/* Modifier keys are the same dark plastic, just a touch deeper. */
#punchkeyboard .m33-key.mod {
    background: radial-gradient(circle at 35% 35%, #4a423a 0%, #241f1a 100%);
}

/* Pressed state: the keycap sinks into the deck. The key moves down by the
   height of the side wall (4px) and the wall collapses, so the cap rests flat
   on the deck — exactly how a flat-top cylinder key feels when pressed. */
#punchkeyboard .m33-key.down {
    transform: translateY(4px);
    box-shadow:
        0 0 0 #241f1a,
        0 2px 4px rgba(0, 0, 0, 0.5);
}

/* Two-line legend: the small top label is the CTRL-code name (letters)
   or the shift symbol (digit row / shifted keys); the base glyph is drawn
   LOW on the cap, as on a real Model 33. */
#punchkeyboard .m33-key .m33-top {
    position: absolute;
    top: 6px;
    left: 0;
    width: 36px;
    text-align: center;
    font-size: 6px;
    font-weight: bold;
    line-height: 1;
    color: #d8dbe0;
    pointer-events: none;
    font-family: arial, helvetica, sans-serif;
    letter-spacing: 0.5px;
}

#punchkeyboard .m33-key.mod .m33-top {
    color: #c8cdd2;
}

/* Keys carrying BOTH a shift symbol and a CTRL-code name (P @ DLE,
   K [ VT, N ^ SO, M ] CR): the shift symbol and the CTRL name sit on the
   SAME line near the top of the round keycap, compact enough to stay
   inside it (total ~28px within the ~29px usable chord at that height). */
#punchkeyboard .m33-key.dual .m33-shift {
    position: absolute;
    top: 7px;
    left: 2px;
    width: 12px;
    text-align: right;
    font-size: 5px;
    font-weight: bold;
    line-height: 1;
    color: #d8dbe0;
    pointer-events: none;
    font-family: arial, helvetica, sans-serif;
}

#punchkeyboard .m33-key.dual .m33-top {
    top: 7px;
    left: 14px;
    width: 16px;
    text-align: left;
    font-size: 5px;
}

#punchkeyboard .m33-key .m33-center {
    position: absolute;
    bottom: 3px;
    left: 0;
    width: 36px;
    height: 16px;
    text-align: center;
    font-size: 13px;
    font-weight: bold;
    line-height: 16px;
    color: #e8e4da;
    pointer-events: none;
    /* Authentic ASR33 keycaps: the base glyph uses a bold sans-serif grotesk
       (not the monospace Courier), matching the other legends on the caps. */
    font-family: arial, helvetica, sans-serif;
}

/* Dark modifier keys carry longer multi-word labels (LINE/FEED, RE-/TURN,
   DE-/LETE, HERE/IS, ...): render them smaller, respect the explicit line
   break baked into the label, and centre the block within the whole keycap
   (they have no small top legend, so nothing sits above to offset). */
#punchkeyboard .m33-key.mod .m33-center {
    color: #e8e4da;
    font-family: arial, helvetica, sans-serif;
    font-size: 7px;
    line-height: 1.15;
    top: 0;
    bottom: auto;
    height: 36px;
    box-sizing: border-box;
    padding: 0 3px;
    display: flex;
    align-items: center;
    justify-content: center;
    white-space: pre-line;
}

/* ---- Space bar: long horizontal bar under the bottom row ---- */

#punchkeyboard .m33-space {
    position: absolute;
    /* As tall as the other keys (36px) and spanning the bottom row from
       the V key to the comma key (196px wide). */
    width: 196px;
    height: 36px;
    border-radius: 18px;
    box-sizing: border-box;
    cursor: pointer;
    user-select: none;
    background: radial-gradient(circle at 50% 30%, #6e6458 0%, #403830 100%);
    border: none;
    box-shadow:
        0 4px 0 #241f1a,
        0 5px 8px rgba(0, 0, 0, 0.4);
}

#punchkeyboard .m33-space.down {
    transform: translateY(4px);
    box-shadow:
        0 0 0 #241f1a,
        0 2px 4px rgba(0, 0, 0, 0.5);
}

/* ==================================================================
   LP11 printer page — the same Google60 rendering as the console
   teletype, but WITHOUT a keyboard and WIDER: a real LP11 prints
   132 columns, so the whole machine is scaled up (1160px) to fit a
   full 132-character line on the paper. The G60Printer instance is
   created with idPrefix "lp11g60", so every generated id is scoped
   under the #lp11_printer container and never collides with the
   console printer. The console teletype (#g60printer) stays 940px.
   ================================================================== */
#lp11_printer {
    position: relative;
    width: 1160px;
    height: 235px;
    background-color: #2a2a2a;
    overflow: hidden;
    border: 1px solid #444;
    margin: 8px 0;
}

#lp11_printer div#lp11g60printer {
    position: absolute;
    top: 0;
    left: 0;
    width: 1160px;
    height: 229px;
    background-color: #6f323d;
    background-image: url('../assets/images/printer_bg.gif');
    background-repeat: repeat;
}

#lp11_printer #lp11g60printheadarea {
    display: block;
    position: absolute;
    /* Halved bay height keeps the head at the same distance from the bay's
       bottom (464 - 388 = 76px → 229 - 76 = 153px). */
    top: 153px;
    left: 67px;
    width: 994px;
    max-width: 994px;
    height: 30px;
    max-height: 30px;
    padding: 0;
    margin: 0;
    z-index: 3;
    overflow: hidden;
}

#lp11_printer #lp11g60printhead {
    display: block;
    position: absolute;
    top: 0;
    left: 16px;
    padding: 0;
    margin: 0;
}

#lp11_printer div#lp11g60printer_frontpannel {
    position: absolute;
    top: 395px;
    left: 67px;
    /* Full machine body width (1160 - 67 left skin - 66 right skin = 1027),
       so the panel seam meets the right skin exactly, matching the console
       teletype (#printer_frontpannel) where width == body width. */
    width: 1027px;
    height: 69px;
    background-image: url('../assets/images/printerskin.png');
    background-repeat: repeat-x;
    background-position: 0 -465px;
    z-index: 2;
}

#lp11_printer div#lp11g60printer_left {
    position: absolute;
    top: 0;
    left: 0;
    width: 67px;
    height: 464px;
    background-image: url('../assets/images/printerskin.png');
    background-repeat: no-repeat;
}

#lp11_printer div#lp11g60printer_right {
    position: absolute;
    top: 0;
    left: 1094px;
    width: 66px;
    height: 464px;
    background-image: url('../assets/images/printerskin.png');
    background-repeat: no-repeat;
    background-position: -67px 0;
}

@media screen and (-webkit-min-device-pixel-ratio:0) {

    #lp11_printer div#lp11g60printer_frontpannel,
    #lp11_printer div#lp11g60printer_left,
    #lp11_printer div#lp11g60printer_right {
        background-image: url('../assets/images/printerskin_webkit.png');
    }
}

#lp11_printer div#lp11g60paper {
    position: absolute;
    top: 0;
    left: 67px;
    width: 1026px;
    height: 400px;
    max-height: 400px;
    vertical-align: top;
    text-align: left;
    padding: 0;
    margin: 0;
    z-index: 1;
}

#lp11_printer div#lp11g60paper.paperNoScroll {
    overflow: hidden;
}

#lp11_printer div#lp11g60paper.paperScroll {
    overflow-y: auto;
    overflow-x: hidden;
}

#lp11_printer div#lp11g60paper_topspacer {
    position: relative;
    height: 345px;
    width: 1px;
    margin: 0;
    padding: 0;
}

#lp11_printer div#lp11g60paper_topspacer.paperScroll {
    height: 16px;
}

#lp11_printer table#lp11g60paper_area {
    margin: 0;
    padding: 0;
    border: 0 none;
    border-collapse: collapse;
    border-spacing: 0;
}

#lp11_printer table#lp11g60paper_area td {
    vertical-align: top;
    margin: 0;
    white-space: nowrap;
}

#lp11_printer td#lp11g60papermargin_left,
#lp11_printer td#lp11g60papermargin_right {
    background-image: url('../assets/images/paper-margin.png');
    background-repeat: repeat-y;
    width: 33px;
    min-width: 33px;
}

#lp11_printer td#lp11g60papermargin_left {
    /* Align the left perforation exactly like the right one (0 0): the old
       -3px shift left a ~3px transparent sliver between the perforation and
       the print area, through which the cabinet showed in the rising paper. */
    background-position: 0 0;
}

#lp11_printer td#lp11g60papermargin_right {
    background-position: 0 0;
}

#lp11_printer td#lp11g60paper_top {
    background-image: url('../assets/images/paper-edge.png');
    background-repeat: repeat-x;
    background-position: 0 0;
    height: 5px;
}

#lp11_printer tr#lp11g60paper_bottom {
    background-image: url('../assets/images/paper-edge.png');
    background-repeat: repeat-x;
    background-position: 0 -5px;
    height: 5px;
    display: none;
}

#lp11_printer td#lp11g60paper_printarea {
    width: 960px;
    color: #36363c;
    font-size: 13px;
    text-align: left;
    font-family: lp1_regular, "Trebuchet MS", sans-serif;
    font-style: normal;
    font-weight: 400;
    line-height: 16px;
    background-color: white;
    padding: 57px 18px 1px 18px;
    white-space: nowrap;
    background-image: url('../assets/images/paper.png');
    background-repeat: repeat;
    -webkit-text-shadow: 0 0 1px rgba(115, 115, 121, 0.6), 0 0 2px rgba(115, 115, 121, 0.3);
    -moz-text-shadow: 0 0 1px rgba(115, 115, 121, 0.6), 0 0 2px rgba(115, 115, 121, 0.3);
    -o-text-shadow: 0 0 1px rgba(115, 115, 121, 0.6), 0 0 2px rgba(115, 115, 121, 0.3);
    text-shadow: 0 0 1px rgba(115, 115, 121, 0.6), 0 0 2px rgba(115, 115, 121, 0.3);
    -webkit-font-smoothing: subpixel-antialiased;
}

#lp11_printer td#lp11g60paper_printarea span {
    display: inline-block;
    vertical-align: top;
    white-space: pre;
    width: 7px;
    max-width: 7px;
    height: 16px;
    max-height: 16px;
    text-align: center;
}

#lp11_printer td#lp11g60paper_printarea span.overstrike {
    background-color: #3a3a3a;
    color: #8a8a8a;
    text-shadow: none;
}

/* Bold / underline emphasis produced by nroff/man overstrike (same glyph
   re-printed → bold; letter printed over an underscore → underline). */
#lp11_printer td#lp11g60paper_printarea span.bold {
    font-weight: bold;
}

#lp11_printer td#lp11g60paper_printarea span.underline {
    text-decoration: underline;
}

#lp11_printer td#lp11g60paper_printarea span.drop {
    margin-top: 1px;
    height: 15px;
    max-height: 15px;
    overflow: hidden;
    text-shadow: 0 -1px 1px rgba(115, 115, 121, 0.7), 0 -1px 2px rgba(115, 115, 121, 0.4);
}

#lp11_printer td#lp11g60paper_printarea span.shift {
    margin-top: -1px;
    text-shadow: 0 1px 1px rgba(115, 115, 121, 0.7), 0 1px 2px rgba(115, 115, 121, 0.4);
}

#lp11_printer td#lp11g60paper_printarea span.nonAscii {
    font-size: 12px !important;
    line-height: 18px !important;
}

#lp11_printer td#lp11g60paper_printarea p {
    margin: 0;
    padding: 0;
    max-height: 16px;
    vertical-align: top;
    white-space: nowrap;
    overflow: visible;
}

#lp11_printer div#lp11g60printer_topoverlay,
#lp11_printer div#lp11g60paper_topshadow {
    position: absolute;
    top: 0;
    left: 67px;
    width: 994px;
    height: 20px;
    padding: 0;
    margin: 0;
    background-image: url('../assets/images/paper-topoverlay.png');
    background-repeat: repeat-x;
}

#lp11_printer div#lp11g60printer_topoverlay {
    z-index: 1;
}

#lp11_printer div#lp11g60paper_topshadow {
    background-position: 0 -21px;
    z-index: 10;
}

/* ==================================================================
   LP11 DEC cabinet — mechanism bay
   The DEC-style enclosure (.lp11-cabinet in pdp11.css) provides the
   cabinet; here the Google60 machine skin is hidden so the LP11 reads
   as a real DEC line printer: a dark mechanics bay showing the fanfold
   paper and the moving print head. Paper + print head keep their
   geometry and animation untouched (applyPaperGeometry uses the JS
   LEFT/RIGHT_SKIN_WIDTH constants, not these elements' sizes).
   These overrides live in THIS file because it is linked AFTER
   pdp11.css, so the same-specificity rules win the cascade.
   ================================================================== */
#lp11_printer {
    /* Beige mechanics bay in the DEC palette (like the cabinet body), with the
       fanfold rising out of a dark slot at the top (see #lp11_printer::before). */
    background: #d6cfbd;
    border: 1px solid #a89f88;
    border-radius: 6px;
    /* visible (not hidden): the rising fanfold paper must be allowed to leave
       the bay through the top slot and climb above the cabinet. */
    overflow: visible;
    box-shadow:
        inset 0 0 26px rgba(0, 0, 0, 0.30),
        0 1px 0 rgba(255, 255, 255, 0.10);
}

#lp11_printer div#lp11g60printer {
    background: linear-gradient(180deg, #e0dac9 0%, #cfc7b2 100%);
}

/* Dark paper opening: a recessed slot right at the carriage, out of which the
   fanfold climbs — the same "indentation" look as the Model 33 ASR punch slot
   (.asr-slot in this file): a black rectangle with rounded corners and an
   inset shadow. It sits BEHIND the paper (z-index 4 < 5), so the sheet never
   disappears behind it while feeding, and is only as tall as the opening
   itself — its bottom edge (bottom:60px) sits where the paper's bottom meets
   the carriage, so the sheet visibly rises out of it instead of the whole bay
   being dark. */
#lp11_printer::before {
    content: "";
    position: absolute;
    bottom: 60px;
    left: 55px;
    width: 1050px;
    height: 16px;
    background: #0a0a0a;
    border: 1px solid #555;
    border-radius: 2px;
    box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.9);
    z-index: 4;
    pointer-events: none;
}

/* Carriage observation window, exactly like the Model 33 ASR's glass window
   (#g60printer::after): a translucent framed pane AROUND the fanfold right at
   the carriage, so the sheet rises out of it. Drawn above the paper/slot
   (z-index 7 > 5), but its background is translucent, so the paper and print
   head stay visible through the pane. */
#lp11_printer::after {
    content: "";
    position: absolute;
    /* Frame the whole paper opening: slightly wider than the dark slot (which
       runs left:55px → width:1050px) and with its bottom edge a little BELOW
       the slot's bottom (bottom:60px), so the slot fits entirely inside it. */
    left: 40px;
    right: 40px;
    bottom: 52px;
    height: 44px;
    border: 2px solid rgba(176, 168, 144, 0.55);
    border-radius: 5px;
    background: linear-gradient(180deg,
            rgba(255, 255, 255, 0.22) 0%,
            rgba(255, 255, 255, 0.05) 45%,
            rgba(140, 128, 104, 0.12) 100%);
    box-shadow: inset 0 2px 8px rgba(0, 0, 0, 0.18),
        0 1px 0 rgba(255, 255, 255, 0.5);
    z-index: 7;
    pointer-events: none;
}

#lp11_printer div#lp11g60printer_left,
#lp11_printer div#lp11g60printer_right,
#lp11_printer div#lp11g60printer_frontpannel {
    display: none;
}

/* ---- LP11: paper rises above the cabinet ----
   Anchor the paper to the BOTTOM of the mechanics bay (its bottom sits at
   404px, right at the print head which stays fixed at 388px), so the fresh
   line always prints under the carriage and older lines ride upward out of
   the top slot. The window grows upward with the content (height:auto) until
   it reaches max-height (its top pokes ~300px above the cabinet); from then
   on the window is fixed and its own scrollbar (belonging to the paper)
   appears, exactly when the paper's top edge reaches the top of the window.
   The Google60 top spacer is removed — otherwise it would shove the fresh
   line up away from the carriage. Scoped to #lp11_printer; the console
   teletype (#g60printer) is untouched. */
#lp11_printer div#lp11g60paper,
#lp11_printer div#lp11g60paper.paperNoScroll,
#lp11_printer div#lp11g60paper.paperScroll {
    top: auto;
    /* Bay height halved: bottom:60px keeps the paper's bottom at 169px so the
       fresh line stays at 153px under the (also moved) print head. max-height
       is viewport-relative (~a cabinet-height offset) so the paper keeps
       growing upward until its top edge reaches the top of the window; the
       paper's own scrollbar then appears right at that moment. The whole
       cabinet is CSS-scaled down on narrow windows (--lp11-scale, set by
       installLP11Scaling in pdp11-app.js), so max-height is divided by the
       live scale — after the transform the fanfold still climbs the same
       fraction of the viewport it would at full size. */
    bottom: 60px;
    height: auto;
    max-height: calc((100vh - 200px) / var(--lp11-scale, 1));
    overflow-y: auto;
    overflow-x: hidden;
}

/* No blank paper tail above the first line (the 345px Google60 top spacer). */
#lp11_printer div#lp11g60paper_topspacer {
    display: none;
}

/* Drop the print-area's 57px top padding so line 1 starts right at the
   top of the paper and the fresh line lands exactly on the carriage. */
#lp11_printer td#lp11g60paper_printarea {
    padding: 4px 18px 1px 18px;
}

/* Hide the Google60 paper-edge overlays: they sit at the TOP of the bay and,
   being above the paper in z-order, would draw "over" the fanfold rising out
   of the slot. */
#lp11_printer div#lp11g60printer_topoverlay,
#lp11_printer div#lp11g60paper_topshadow {
    display: none;
}

/* The rising fanfold and the moving print head must stay above the DEC hood
   (.lp11-hood in css/pdp11.css): the hood is drawn in the cabinet BEFORE the
   mechanics bay in the DOM, so give the paper/head an explicit z-index above
   it — the paper visibly climbs out of the hood's central paper slot. */
#lp11_printer div#lp11g60paper,
#lp11_printer #lp11g60printheadarea {
    z-index: 5;
}

/* ==================================================================
   Model 33 ASR console teletype — paper grows upward like the LP11.
   The console paper behaves exactly like the LP11 printer page: it is
   anchored to the BOTTOM of the machine (its bottom sits right at the
   carriage, which stays fixed at ~400px), so the fresh line always
   prints under the carriage and older lines ride upward out of the top
   of the machine. The paper window grows upward with the content
   (height:auto) until it reaches max-height — set by
   installTeletypePaperGrowth() in pdp11-app.js so the paper's top edge
   reaches the TOP of the browser window; from then on the window is
   fixed and its own scrollbar appears, exactly like the LP11 fanfold.
   The Google60 top spacer is removed — otherwise it would shove the
   fresh line up away from the carriage. Scoped to #g60printer; the
   LP11 printer page (#lp11_printer) is untouched.
   ================================================================== */
/* Let the rising paper leave the top of the machine body. */
#g60printer {
    overflow: visible;
}

/* Anchor the paper to the bottom (bottom:52px keeps its lower edge at
   the BOTTOM of the print-head area, 380px - 52px = 328px). max-height is
   viewport-driven via the CSS variable set by installTeletypePaperGrowth();
   400px is the pre-JS fallback. The print-area's extra 12px bottom padding
   keeps the carriage (the fresh-line baseline) at its original position —
   the sheet itself just extends 12px further down into the machine, so it
   reads as one continuous roll with no visible seam. */
#g60printer div#paper,
#g60printer div#paper.paperNoScroll,
#g60printer div#paper.paperScroll {
    top: auto;
    bottom: 52px;
    height: auto;
    max-height: var(--tty-paper-max, 400px);
    overflow-y: auto;
    overflow-x: hidden;
}

/* No blank paper tail above the first line (the 345px Google60 top spacer). */
#g60printer div#paper_topspacer {
    display: none;
}

/* Drop the print-area's 57px top padding so line 1 starts right at the
   top of the paper and the fresh line lands exactly on the carriage.
   The bottom padding is 13px (1px base + 12px extra): because the paper
   element itself now extends 12px further down (bottom:52px → 328px), the
   extra bottom padding keeps the fresh-line baseline at its original
   position while the paper's own background fills the 12px below it —
   the sheet continues seamlessly into the machine like a paper roll. */
#g60printer td#paper_printarea {
    padding: 4px 18px 13px 18px;
}

/* Hide the Google60 paper-edge overlays: they sit at the TOP of the
   machine and, being above the paper in z-order, would draw "over" the
   paper rising out of the top. */
#g60printer div#printer_topoverlay,
#g60printer div#paper_topshadow {
    display: none;
}

/* ==================================================================
   Model 33 ASR — tape reader / punch unit and the punched paper tape.
   The ASR block sits to the LEFT of the printer + keyboard (see the
   #page-teletype markup in pdp11.html). Every byte echoed to the
   console punches one row of holes on the tape (#punchtape), which
   grows downwards; once it overflows the window a scrollbar appears
   and the view follows the freshly punched row (see punchtape.js).
   ================================================================== */
#teletype-rig {
    display: flex;
    flex-direction: row;
    justify-content: center;
    align-items: stretch;
    gap: 12px;
}

#asr-tape-unit {
    position: relative;
    /* Cabinet: the punch sits ABOVE the reader in one vertical stack (as on
       the historical machine), and the punched tape hangs below the punch.
       The cabinet is only as wide as the punch/reader blocks, which keep
       their original ~144px width, so the tape hangs centred under the
       punch. The BOTTOM is aligned with the bottom of the keyboard deck
       (#punchkeypane: 396px top + 240px height = 636px); the taller 360px
       cabinet grows UPWARD (top at 276px) and, together with the 10px
       top/bottom insets on #asr-mech, leaves clear breathing room above
       the punch and below the reader. */
    width: 170px;
    height: 360px;
    margin-top: 276px;
    /* Sand ASR33 body, matching the printer + keyboard deck. */
    background-color: #d1b48c;
    border: 1px solid #a68c66;
    border-radius: 8px;
    box-shadow: 0 4px 10px rgba(0, 0, 0, 0.25);
    overflow: visible;
    /* let the punched tape spill past the cabinet */
    align-self: flex-start;
}

#asr-mech {
    position: absolute;
    left: 0;
    top: 0;
    right: 0;
    bottom: 0;
    display: flex;
    /* Punch above reader, matching the historical layout. The blocks keep
       their original narrow width and are centred in the narrow cabinet.
       10px vertical padding insets BOTH metal panels from the cabinet's top
       and bottom edges, so neither the punch nor the reader touches the
       sand cabinet frame. */
    flex-direction: column;
    align-items: center;
    padding: 10px 0;
    /* Same gap between the punch and the reader as between the reader and
       the teletype keyboard (see the 12px gap on #teletype-rig). With
       flex:1 children the gap is carved out of the padded cabinet, so the
       punch and the reader each get (360 - 20 - 12) / 2 = 164px. */
    gap: 12px;
}

/* Punch: on top — same size as the reader, keeping the original narrow
   width (144px, one half of the former 300px row cabinet). The punch and
   reader surfaces use the SAME cream as the LINE/OFF/LOCAL block
   (#ccu-apron), so the whole ASR unit reads as one plastic body. */
#asr-punch {
    position: relative;
    flex: 1 1 0;
    width: 144px;
    align-self: center;
    background: linear-gradient(180deg, #ddd6c4 0%, #ccc5b0 100%);
    border-bottom: 1px solid #b3ab94;
    border-radius: 8px 8px 0 0;
    /* Same drop + inner-top highlight as the LINE/OFF/LOCAL block (#ccu-apron). */
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, 0.6),
        0 1px 3px rgba(0, 0, 0, 0.35);
}

/* Reader: at the bottom — same size as the punch, keeping the original
   narrow width. Same cream surface as the punch above it and as the
   LINE/OFF/LOCAL block (#ccu-apron). */
#asr-reader {
    position: relative;
    flex: 1 1 0;
    width: 144px;
    align-self: center;
    background: linear-gradient(180deg, #ddd6c4 0%, #ccc5b0 100%);
    border-radius: 0 0 8px 8px;
    /* Same drop + inner-top highlight as the LINE/OFF/LOCAL block (#ccu-apron). */
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, 0.6),
        0 1px 3px rgba(0, 0, 0, 0.35);
}

.asr-label {
    position: absolute;
    top: 3px;
    left: 0;
    right: 0;
    text-align: center;
    font-family: arial, helvetica, sans-serif;
    font-size: 10px;
    font-weight: bold;
    letter-spacing: 2px;
    color: #5c5442;
    text-shadow: 0 1px 0 rgba(255, 255, 255, 0.6);
}

.asr-slot {
    position: absolute;
    left: 50%;
    top: 106px;
    /* Wider than the punched tape (97px) but clearly narrower than the
       punch/reader cabinet, so the opening's dark walls stay visible around
       the tape as it passes through (the tape draws on top of the slot).
       top:106px keeps the slot's distance to the block BOTTOM (26px) the
       same as before the cabinet was made taller. */
    width: 104px;
    height: 12px;
    margin-left: -52px;
    background: #0a0a0a;
    border: 1px solid #555;
    border-radius: 2px;
    box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.9);
}

/* Triangular tongue sitting ON TOP of the punch tape-out slot, forming one
   solid piece with the punch cabinet (same gradient): a full triangle whose
   BASE is as wide as the slot itself (104px), attached to the TOP edge of
   the slot, and whose NOSE points straight DOWN, reaching the BOTTOM edge
   of the slot. top:-1px makes the base overlap the slot's 1px top border so
   no hairline crack shows between the tongue and the cabinet above. The
   dark slot walls show through as the two triangular notches on either side
   of the nose. It draws ABOVE the hanging tape, so the punched tape appears
   to pass out from UNDER it. */
#asr-punch .asr-slot::before {
    content: "";
    position: absolute;
    left: 50%;
    top: -1px;
    transform: translateX(-50%);
    width: 104px;
    height: 13px;
    background: linear-gradient(180deg, #ddd6c4 0%, #ccc5b0 100%);
    clip-path: polygon(0 0, 100% 0, 50% 100%);
    z-index: 20;
}

/* Both slots stay centred on their block (left:50% from the base rule): the
   punch slot lets the tape hang straight down from the middle of the punch,
   and the reader slot sits centred below it. */

/* Punch operator buttons (REL/OFF/BSP/ON) arranged in a 2x2 block in the
   punch cabinet BETWEEN the TAPE PUNCH label and the tape-out slot, so the
   tape spilling from the slot never covers them. The DOM order REL/OFF/BSP/ON
   wraps into two rows — REL OFF on the top, BSP ON below — matching the
   historical machine. REL releases the tape; BSP backspaces the tape one
   step; OFF/ON toggle the punch (OFF by default). On a real Model 33 ASR
   these are round (circular) push-buttons.
   The 2x2 block spans exactly the width of the tape-out slot below it
   (104px, same left offset): with justify-content: space-between the left
   column (REL/BSP) hugs the slot's LEFT edge and the right column (OFF/ON)
   hugs the slot's RIGHT edge. */
.asr-punch-buttons {
    position: absolute;
    left: 50%;
    top: 18px;
    margin-left: -52px;
    /* Matches the slot's OUTER (border-box) width exactly: the slot is
       width:104px content + 2px borders = 106px, so with box-sizing:
       border-box and the same left offset the buttons span the full slot
       width and their outer edges align with the slot's outer edges.
       A 2x2 CSS grid (guaranteeing exactly two buttons per row) with
       justify-content: space-between presses the left column (REL/BSP) to
       the slot's LEFT edge and the right column (OFF/ON) to its RIGHT edge,
       leaving only a 4px row gap between the two rows. */
    width: 106px;
    box-sizing: border-box;
    display: grid;
    grid-template-columns: 30px 30px;
    grid-auto-rows: 30px;
    justify-content: space-between;
    align-content: start;
    row-gap: 4px;
    /* top:38px keeps the 2x2 block's distance to the block BOTTOM (42px)
       the same as before the cabinet was made taller; the extra height now
       sits between the TAPE PUNCH label and the buttons. */
    top: 38px;
}

.asr-btn {
    background: linear-gradient(180deg, #5a4a30, #3a3528);
    color: #f0e6c8;
    border: 1px solid #c8a860;
    /* Round push-button: fixed width == height with 50% radius gives a true
       circle (a pill would only be an ellipse); text is centred via flex.
       Generous diameter so the 3-letter legends (ON/OFF/BSP/REL) sit well
       clear of the circle edge. */
    width: 28px;
    height: 28px;
    border-radius: 50%;
    padding: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-family: arial, helvetica, sans-serif;
    font-size: 8px;
    font-weight: bold;
    cursor: pointer;
}

.asr-btn:hover {
    filter: brightness(1.15);
}

/* Punch is ON: the ON button lights up. */
.asr-btn.active {
    background: linear-gradient(180deg, #8a6a30, #5a4a28);
    color: #ffe9a8;
    border-color: #e8c878;
}

/* Four-position tape reader switch (START/STOP/FREE/AUTO) styled like the
   CCU line switch (LINE/OFF/LOCAL): a round rotary knob with a light centre,
   a gray ring and a protruding triangular beak that points at the active
   position. The JS rotates #reader-switch-lever (0/90/180/270°), so the beak
   orbits the disc centre and lands on START/STOP/FREE/AUTO. */
.asr-reader-switch {
    position: absolute;
    /* Centre the switch in the TAPE READER cabinet: the reader keeps its
       original 144px width, so its switch centre sits at 75px; with a 92px
       switch that means left = 75 - 46 = 29px. top:42px keeps the switch's
       distance to the block BOTTOM (40px) the same as before the cabinet
       was made taller. The hanging punch tape draws ABOVE it (see
       #punchtape z-index), as a punched tape always passes in front of the
       reader mechanism. */
    left: 29px;
    top: 42px;
    width: 92px;
    height: 62px;
}

.asr-switch-disc {
    position: absolute;
    left: 26px;
    top: 13px;
    width: 36px;
    height: 36px;
    border-radius: 50%;
    /* Light centre inside a thick gray ring, matching the CCU knob. */
    background: radial-gradient(circle at 50% 50%,
            #f6f6f6 0%,
            #e0e0e0 58%,
            #8a8a8a 68%,
            #7e7e7e 94%,
            #949494 100%);
    box-shadow:
        inset 0 0 0 1px rgba(0, 0, 0, 0.12),
        0 2px 3px rgba(0, 0, 0, 0.4);
}

/* Triangular beak, like the CCU knob, sticking out of the disc. It rotates
   around the disc centre: the beak box sits at top:-8px, so an origin 26px
   below its top lands exactly on the disc centre (13px + 18px). */
.asr-switch-lever {
    position: absolute;
    left: 50%;
    top: -8px;
    width: 10px;
    height: 8px;
    margin-left: -5px;
    background: linear-gradient(180deg, #d0d0d0 0%, #8a8a8a 100%);
    clip-path: polygon(50% 0, 100% 100%, 0 100%);
    transform-origin: 50% 26px;
    transition: transform 0.2s;
    pointer-events: none;
    z-index: 2;
}

/* Position labels around the disc, kept clear of the disc. */
.asr-switch-pos {
    position: absolute;
    background: transparent;
    border: 0;
    padding: 0;
    color: #5c5442;
    font-family: arial, helvetica, sans-serif;
    font-size: 7px;
    font-weight: bold;
    letter-spacing: 1px;
    cursor: pointer;
}

/* START sits above the disc: its horizontal centre aligns with the disc
   centre (X = 26 + 36/2 = 44px). */
.asr-switch-pos[data-reader-mode="start"] {
    left: 44px;
    top: 0;
    transform: translateX(-50%);
}

/* STOP sits to the right of the disc, clear of the rotating beak: its
   vertical centre aligns with the disc centre (Y = 8 + 36/2 = 26px). */
.asr-switch-pos[data-reader-mode="stop"] {
    left: 76px;
    top: 31px;
    transform: translateY(-50%);
}

/* FREE sits below the disc: its horizontal centre aligns with the disc
   centre (X = 44px). */
.asr-switch-pos[data-reader-mode="free"] {
    left: 44px;
    bottom: 0;
    transform: translateX(-50%);
}

/* AUTO sits to the left of the disc, clear of the rotating beak: its
   vertical centre aligns with the disc centre (Y = 26px). */
.asr-switch-pos[data-reader-mode="auto"] {
    left: -14px;
    top: 31px;
    transform: translateY(-50%);
}

.asr-switch-pos.active {
    /* Same highlighted colour as the CCU LINE/OFF/LOCAL active state. */
    color: #7a5a20;
    text-shadow: 0 0 4px rgba(122, 90, 32, 0.5);
}

/* ---- The hanging punched tape ----
   #punchtape hangs from the TAPE PUNCH slot down to the bottom of the
   window. It is absolutely positioned (out of the flow), so a growing tape
   never resizes the teletype page. The fresh row is prepended at the top
   (right under the punch head); the tape spills downwards until its lower
   end reaches the bottom of the window, at which point its own scrollbar
   appears (overflow-y: auto). punchtape.js sets max-height so the tape
   reaches the window edge; 60vh is only the pre-JS fallback. */
#punchtape {
    position: absolute;
    /* Emerge from the MIDDLE of the TAPE PUNCH slot: the punch block starts
       at the 10px #asr-mech top inset and the slot sits at top 106px within
       it, so the slot centre lands at 10 + 106 + 6 = 122px. Horizontally
       centred on the punch: the punch block is 144px wide centred in the
       170px cabinet, so its centre sits at 85px; tape left = 85 - 48.5 ≈
       36px. Draws ABOVE every other element of the ASR unit (the reader
       switch, the slots), so the punched tape always passes in front of the
       mechanism. */
    top: 122px;
    left: 36px;
    z-index: 10;
    /* Tape body (97px) PLUS a reserved scrollbar gutter (10px) with a
       transparent background: scrollbar-gutter: stable reserves the gutter
       up front in EVERY browser, so the scrollbar never resizes the tape or
       shifts it left, and there is no dark gutter strip (the tape sits on the
       page background on both sides). */
    width: 107px;
    max-width: 100%;
    height: auto;
    max-height: 60vh;
    overflow-y: auto;
    overflow-x: hidden;
    scrollbar-gutter: stable;
}

.punchtape__body {
    display: flex;
    flex-direction: column;
    /* Left-aligned: the tape hugs the punch slot, and the reserved scrollbar
       gutter sits on its right without covering the tape. */
    align-items: flex-start;
    padding: 0;
    /* Solid tape colour matching .pt-row. Under the rig's transform: scale a
       12px row lands on a fractional pixel, and the browser rounds each row
       individually, leaving hairline horizontal seams between them through
       which the cabinet showed as stripes. Painting the whole body the tape
       colour makes those subpixel seams invisible (white-on-white). */
    background: #f6f1e5;
}

/* Ragged bottom edge of the tape, matching the teletype paper edge.
   The paper-edge.png strip is the teletype's TOP paper edge; flip it
   vertically so it becomes the tape's ragged BOTTOM edge. */
.punchtape__body::after {
    content: "";
    display: block;
    flex: 0 0 auto;
    width: 100%;
    height: 5px;
    background-image: url('../assets/images/paper-edge.png');
    background-repeat: repeat-x;
    background-position: 0 0;
    transform: scaleY(-1);
}

/* ---- One punched row ----
   Rows are packed edge-to-edge (no vertical margin), so the tape reads as a
   continuous strip: each row is exactly one 10-char-per-inch tape step. */
.pt-row {
    display: flex;
    flex-direction: row;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    height: 12px;
    padding: 0 1px;
    box-sizing: border-box;
    /* Solid white tape body — no per-row gradient and no side borders, so
       the packed rows read as one continuous plain (unstriped) paper tape. */
    background: #f6f1e5;
}

/* Narrow blank margins on both sides of the tape (real tape has small
   unpunched edges, not wide fields) */
.pt-cell {
    flex: 0 0 2px;
    width: 2px;
    height: 12px;
    background-color: transparent;
}

/* Data holes (tracks Д1..Д8) */
.pt-hole {
    flex: 0 0 8px;
    width: 8px;
    height: 12px;
    margin: 0 1px;
    box-sizing: border-box;
}

.pt-hole.on {
    background: radial-gradient(circle at 50% 50%, #1c1712 0%, #1c1712 45%, transparent 60%);
    background-size: 7px 7px;
    background-repeat: no-repeat;
    background-position: 50% 50%;
}

/* Feed (sprocket) hole — always punched, between tracks Д3 and Д4 */
.pt-sprocket {
    flex: 0 0 7px;
    width: 7px;
    height: 12px;
    margin: 0 2px;
    background: radial-gradient(circle at 50% 50%, #1c1712 0%, #1c1712 42%, transparent 58%);
    background-size: 6px 6px;
    background-repeat: no-repeat;
    background-position: 50% 50%;
}

/* ==================================================================
   Model 33 ASR operator controls (Tear tape, Tear paper, Save tape).
   A single row of push-buttons under the machine, styled to match the
   real-printer action buttons (see .printer-actions button in
   css/pdp11.css) so the teletype and LP11 pages look alike.
   ================================================================== */
#teletype-controls {
    /* Pin the operator buttons to the bottom of the screen, centred on the
       page rather than under the teletype — same treatment as the front-panel
       action buttons (.panel-actions in css/pdp11.css): absolute inside
       #page-teletype (which is position: relative), a full-width flex row
       centred with the same 12px bottom offset as the PANEL buttons. */
    position: absolute;
    left: 0;
    right: 0;
    bottom: 12px;
    display: flex;
    gap: 10px;
    justify-content: center;
    padding: 0;
}

.tty-btn {
    background: linear-gradient(180deg, #5a4a30, #3a3528);
    color: #f0e6c8;
    border: 1px solid #c8a860;
    border-radius: 4px;
    padding: 6px 16px;
    font-size: 12px;
    font-weight: bold;
    cursor: pointer;
    margin: 0 6px;
}

.tty-btn:hover {
    background: linear-gradient(180deg, #6a5a38, #4a3a2c);
}

/* ==================================================================
   Model 33 ASR Call Control Unit (CCU) — rotary LINE/OFF/LOCAL switch.
   On a real Model 33 ASR the line switch is a round dark-plastic knob
   with a protruding "beak" pointer, mounted on a small flat plastic
   apron to the RIGHT of the keyboard, level with its lower edge. The
   knob has three fixed detents: LINE (left), OFF (centre, power
   fully off) and LOCAL (right). The apron sits in the lower-right
   corner of the keyboard deck (#punchkeypane), clear of the keys.
   ================================================================== */
#ccu-apron {
    position: absolute;
    right: 14px;
    bottom: 10px;
    width: 118px;
    height: 66px;
    background: linear-gradient(180deg, #ddd6c4 0%, #ccc5b0 100%);
    border: 1px solid #b3ab94;
    border-radius: 4px;
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.6), 0 1px 3px rgba(0, 0, 0, 0.35);
    z-index: 2;
}

.ccu-switch {
    position: absolute;
    left: 0;
    top: 0;
    right: 0;
    bottom: 0;
}

/* Round knob: a circle with a thick gray ring and a light centre. The
   whole knob (disc + beak) rotates around its OWN centre like a real
   rotary knob: the small triangular beak is a child of the disc, so it
   orbits the centre as the knob turns. LINE = -60°, OFF = 0° (up),
   LOCAL = +60°. */
.ccu-switch-disc {
    position: absolute;
    left: 50%;
    bottom: 6px;
    width: 34px;
    height: 34px;
    margin-left: -17px;
    border-radius: 50%;
    /* Light centre inside a thick gray ring, drawn as one radial
       gradient (no border, so the beak's bottom:100% lands exactly on
       the knob's outer edge). Symmetric (50% 50%) so rotating the knob
       is invisible except for the beak. */
    background: radial-gradient(circle at 50% 50%,
            #f6f6f6 0%,
            #e0e0e0 58%,
            #8a8a8a 68%,
            #7e7e7e 94%,
            #949494 100%);
    box-shadow:
        inset 0 0 0 1px rgba(0, 0, 0, 0.12),
        0 2px 3px rgba(0, 0, 0, 0.4);
    transform-origin: 50% 50%;
    transition: transform 0.2s;
    z-index: 2;
}

/* Small triangular beak that sticks out of the gray ring. As a child of
   the disc it rotates with the knob around the disc centre: its base
   sits on the ring (bottom:100% = the knob's outer edge) and the tip
   points outward. */
.ccu-switch-lever {
    position: absolute;
    left: 50%;
    bottom: 100%;
    width: 10px;
    height: 8px;
    margin-left: -5px;
    background: linear-gradient(180deg, #d0d0d0 0%, #8a8a8a 100%);
    clip-path: polygon(50% 0, 100% 100%, 0 100%);
    pointer-events: none;
    z-index: 3;
}

/* Position labels around the knob, drawn on the apron body. */
.ccu-switch-pos {
    position: absolute;
    background: transparent;
    border: 0;
    padding: 0;
    color: #5c5442;
    font-family: arial, helvetica, sans-serif;
    font-size: 7px;
    font-weight: bold;
    letter-spacing: 1px;
    cursor: pointer;
}

/* OFF sits above the knob, centred. */
.ccu-switch-pos[data-tty-mode="off"] {
    left: 50%;
    top: 2px;
    transform: translateX(-50%);
}

/* LINE sits to the left of the knob. */
.ccu-switch-pos[data-tty-mode="line"] {
    left: 5px;
    top: 26px;
}

/* LOCAL sits to the right of the knob. */
.ccu-switch-pos[data-tty-mode="local"] {
    right: 5px;
    top: 26px;
}

.ccu-switch-pos.active {
    color: #7a5a20;
    text-shadow: 0 0 4px rgba(122, 90, 32, 0.5);
}