TechNoviceTools — Est. 2015

Danger Will Robinson!
& Eureka Moments

A running log of coding disasters survived —
and surprising discoveries worth remembering.

What Are DWR & Eureka Moments?

Robot warning Will Robinson — Lost in Space

D.W.R. — Danger Will Robinson!

Remember the Robot from Lost in Space flailing its arms and warning young Will Robinson of impending doom? That’s us — warning you. A DWR entry is a coding pitfall we stumbled into so you don’t have to — or at least so you recognize the cliff when you’re standing at the edge.

Never seen the Robot in action? Fix that immediately. →

Archimedes in his bathtub — the original Eureka moment

Eureka Moments

Named for Archimedes’ legendary bathtub shout. A Eureka entry is a discovery — something cool we figured out, a technique that clicked, or a tool that made us say “Wait, you can DO that?!” Worth writing down so we can find it again.

Both are part of the same learning loop: blow something up, figure out why, write it down. That’s the TNT way.

Moments & Milestones

Newest entries at the top. Click any title arrow to expand the full story.

Date App / Topic Type
06/09/2026

F4 Whole Team Template — Never Write </body> (or Any Closing Tag) Inside an HTML Comment

Read more…

A Copilot-generated comment at the bottom of the page included the literal closing tag </body> as a label. The result was strange: text that belonged inside the comment appeared as visible fragments at the very bottom of the rendered page.

What the Comment Looked Like

The comment block near the end of the file read something like:

<!-- END OF PAGE
     </body> and </html> close below
-->

Why It Broke

Same family of problem as Entry 8. The HTML5 parser watches for certain tag sequences everywhere — including inside comments. When the browser encountered </body> inside the comment, it treated it as the real end of the document body. Everything that followed — including the rest of the comment text and the actual closing tags below it — was pushed outside the body element. Browsers sometimes render that stray content as visible text at the very bottom of the page.

The symptom was odd comment fragments appearing as page text. The cause was a tag that was never meant to be parsed, being parsed anyway.

The Fix

Replace any closing tag text in comments with plain descriptive words:

<!-- END OF PAGE
     body end and html end close below
-->

Same intent. Zero parser side effects.

The Rule: Never write </body>, </html>, <script>, or any tag-like text inside an HTML comment. The HTML5 parser does not fully ignore comments — it still scans for certain tag sequences. Use plain descriptive words instead. This is the same root cause as Entry 8; closing tags are just as dangerous as opening ones.

DWR
06/09/2026

F4 Whole Team Template-- Inside an HTML Comment Breaks XML Validation

Read more…

The W3C validator flagged this as an info message — not a hard error, but it signals a real incompatibility worth knowing.

What Triggered It

A comment block used -- as a decorative section divider:

<!-- -- ABOUT EXTERNAL STYLESHEETS -------------------------------- -->

The message was: “The document is not mappable to XML 1.0 due to two consecutive hyphens in a comment.”

Why It Happens

The XML 1.0 specification reserves the sequence -- exclusively for comment delimiters: <!-- to open and --> to close. Using -- anywhere else inside a comment is technically illegal in XML, because a parser could misinterpret it as an attempt to close the comment. HTML5 browsers handle it gracefully, but the W3C validator checks against both HTML5 and XML 1.0 rules simultaneously.

The Fix

Replace -- section markers with any other character. We use ==:

<!-- == ABOUT EXTERNAL STYLESHEETS ================================ -->

Visually identical. Completely valid. One character change.

The Rule: Inside an HTML comment, -- may only appear as part of --> at the very end. Use =, ~, #, or any other character as a visual separator everywhere else.

DWR
06/09/2026

F4 Whole Team Template — Never Write <script> Inside an HTML Comment (Near a Real Script Tag)

Read more…

The Bootstrap modals and accordion on the page were completely silent — clicking cards and buttons did nothing. The browser console showed a cryptic error: “Uncaught SyntaxError: Unexpected token ‘,’” at a line number that didn’t even exist in our source file. That last detail was the key clue: when an error points to a non-existent line, the JavaScript parser has gone off the rails somewhere before that line and is trying to parse HTML as if it were code.

What We Had Written

The comment block just above the Bootstrap JS bundle tag read:

<!-- BOOTSTRAP JS BUNDLE - always last, just before </body>
     Without this <script>, the data-bs-* attributes won't work.
-->
<script src="...bootstrap.bundle.min.js"></script>

That looks completely harmless. It’s an HTML comment. Comments are ignored, right?

Why It Broke

HTML5 parsers have a special rule when they are scanning for script tags: they watch for the sequence <script anywhere in the document, even inside comments. When the parser saw <script> inside the comment, some browsers switched into script-parsing mode immediately — before reaching the closing -->. Once in script mode, the next thing the browser read was:

, the data-bs-* attributes won't work.
-->

That leading comma is valid HTML inside a comment, but it is completely illegal as the first token of a JavaScript statement. The parser threw “unexpected token ‘,’” and aborted the entire script block. Bootstrap never finished loading. Every component that depends on Bootstrap’s JavaScript — modals, accordions, dropdowns — was silently dead.

Why It Was Hard to Find

Three things made this especially tricky:

  • The error message (“unexpected token ‘,’”) pointed to a line number higher than our file’s total line count — meaning the parser had gone completely off-road.
  • The comment itself was valid HTML and visually looked fine.
  • The symptom (modals not opening) had many possible causes and gave no obvious clue about HTML comments.

We also found that decorative Unicode box-drawing characters (═ and ─) used inside /* */ JavaScript comments caused the same family of problem. Some browsers reject non-ASCII characters in script blocks entirely, even inside comments. Those had to be replaced with plain hyphens and equals signs.

The Fix

Replace any <script> or </script> tags written inside HTML comments near actual script blocks with plain descriptive text:

<!-- BOOTSTRAP JS BUNDLE - always last, just before </body>
     Without this JS bundle, the data-bs-* attributes won't work.
-->

The word “bundle” is clearer anyway.

The Rules to Remember

  1. Never write <script> or </script> inside an HTML comment that is near a real script block. The HTML5 parser will sometimes treat it as a real tag opener even inside a comment.
  2. Never use non-ASCII characters (Unicode box-drawing, smart quotes, em-dashes, etc.) inside a <script> block — even inside /* */ comments. Stick to plain ASCII. Those decorative characters are fine in HTML; they are not safe in JavaScript.
  3. When a JS error points to a line that doesn’t exist in your source file, the parser got confused long before that line. Work backwards from the last real script block and check what’s just outside it.
DWR
06/06/2026

TNT Image Gallery — TTG Acronym Tip + Precision Link to the Exact About Us Section

Read more…

We had a gallery comment that said TTG, but curious students had to hunt around manually to decode it. The navigation improvement was simple: make the acronym self-explanatory and link directly to the exact profile section in About Us.

Step 1: Clarify the acronym in-place

In the Slide Rule entry, TTG was wrapped with an abbreviation tooltip so hovering the acronym reveals its full meaning:

<abbr title='Tech Tools Guru'>TTG</abbr>

Step 2: Add a deep-link target to About Us

The TTG card in About Us received a stable anchor id:

<div class="about-card" id="ttgProfile">...</div>

Then the gallery link points directly there:

<a href='aboutUs.html#ttgProfile'>About Us</a>

Why This Is a Eureka

This is small-code, high-impact navigation design: students click once and land exactly where context lives. It reduces friction, reinforces acronym literacy, and models a best practice for internal documentation links across the site.

Live example: Open the Circular Slide Rule gallery entry and click its About Us link.

Eureka
06/06/2026

TNT Image Gallery — Neat Trick: Open a Specific Modal from a Hyperlink

Read more…

We wanted a link on Loud Pictures movie page that did more than navigate to the gallery. The goal was to jump to the gallery and automatically open the exact card modal for Loud Pictures. It worked with one query parameter and a tiny startup script.

Step 1: Put the target title in the link URL

The link passes the card title through ?open=...:

<a href="../tnt_image_gallery.html?open=Loud%20Pictures#galleryGrid">
  Open the gallery entry directly
</a>

Step 2: Read the URL and click the matching card

On gallery page load, JavaScript checks for open, finds the matching data-title, scrolls it into view, and triggers a click so Bootstrap opens the modal:

const openTitle = new URLSearchParams(window.location.search).get('open');
if (openTitle) {
  const cards = document.querySelectorAll('.gallery-item');
  const targetCard = Array.from(cards).find(card => card.dataset.title === openTitle);

  if (targetCard) {
    targetCard.scrollIntoView({ behavior: 'smooth', block: 'center' });
    setTimeout(() => targetCard.click(), 250);
  }
}

Why This Is a Eureka

This creates deep-link behavior without duplicating pages. One reusable modal still powers the whole gallery, but outside pages can point directly to a specific entry by title. Students click one link and land exactly where the lesson needs them.

Live example: Open Loud Pictures movie page, then click “Open the gallery entry directly.”

Eureka
06/06/2026

TNT Image Gallery — Let CSS Stamp AI Entries with a Robot Marker

Read more…

Originally we were about to manually type a robot marker in front of every gallery blurb generated by Claude. Then we realized the browser can do that automatically with a CSS pseudo-element. That turned a repetitive editing job into one clean styling rule. You can see the live note in the gallery intro here: AI marker note in TNT Image Gallery.

How the Technology Works

A pseudo-element is a virtual element created by CSS. It is not written in the HTML, but it behaves like content that appears before or after an element’s text. With ::before, you target a class (in our case .aiEntry) and tell CSS to inject text using the content property.

<!-- Step 1: wrap AI-authored blurbs in a semantic class -->
<button data-desc="<span class='aiEntry'>AI-generated blurb text...</span>">
    ...
</button>

/* Step 2: style the AI blurb text itself */
.aiEntry {
    color: #6d6e6e;
    font-family: 'Courier New', Courier, monospace;
    display: block;
}

/* Step 3: inject marker content before every AI blurb */
.aiEntry::before {
    content: "🤖:";
    font-weight: bold;
    margin-right: 0.5em;
}

Translation: every element with class aiEntry gets a robot label automatically at render time. No copy/paste. No risk of forgetting one entry. Update the marker once in CSS and the whole gallery updates instantly.

Quick swap trick. If you ever want a different prefix, change just one line:

.aiEntry::before { content: "AI:"; }

That single edit updates every AI marker in the gallery.

Why This Was a Eureka

This is a textbook separation-of-concerns win. HTML holds meaning and content; CSS controls presentation. The blurbs stay clean, while the “AI speaker tag” lives in one reusable design rule. Less manual work, fewer mistakes, and a style system that scales.

Practical Caveat

Generated content from CSS is mainly visual. If a prefix is mission-critical information (not just a display cue), consider including that meaning in real HTML too. For our gallery context, the pseudo-element marker is exactly the right level of lightweight UI annotation.

Eureka
06/05/2026

Ask Copilot — “Your <article> has no heading” & the role="banner" Misuse

Read more…

When we ran the HTML validator on the Ask Copilot page, it came back with about ten identical warnings and one extra. All of them were quiet, easy-to-miss validator info messages — not hard errors, but still worth caring about. Here’s what they meant and why we fixed them.

Warning 1 (×10): “Article lacks heading”

What it means. In HTML, an <article> element is supposed to be a self-contained piece of content — like a newspaper article, a blog post, or (in our case) a Q&A entry. The HTML spec says each one should have a heading so that screen readers can announce what the article is about before reading it. Think of it like giving each newspaper column entry a headline: without one, a blind reader hears all the content but never hears a title.

Why we caused it. Each Ask Copilot entry had a label like “Entry #010 • Jun 2026” styled as a <span>. A <span> is invisible to screen readers as a structural landmark — it’s just a styling hook. The browser can’t tell it apart from any other text on the page.

The fix. We promoted each span to an <h3> element, which is a proper heading. Since browsers render <h3> with big text and margins by default, we had to add a small CSS reset to make it look exactly like the old span — same tiny uppercase text, no extra spacing.

/* Reset heading defaults so it looks like the original span */
.column-entry-num {
    font-size:   0.66rem;
    font-weight: 700;
    margin:      0;         /* ← the key reset — removes h3 margin */
    padding:     0;
    font-family: inherit;   /* don't use the heading font stack */
}

Why should you care? Roughly 1-in-25 people uses assistive technology at some point. Writing semantic HTML costs nothing extra — it’s just choosing the right tag. Using <h3> instead of <span> is the same amount of code; one means something to the browser, and one doesn’t. The visual result is identical. The accessible result is completely different.

Warning 2 (×1): role="banner" in the Wrong Place

What it means. ARIA roles tell screen readers what a section of the page is. The banner role specifically means “this is the site’s main header — the logo and navigation at the very top.” Every page is allowed exactly one banner, and it must be at the top level of the document, not buried inside <main>.

Why we caused it. The Ask Copilot page has a newspaper-style masthead inside the article column (the big “ASK COPILOT” nameplate). Someone added role="banner" to it because it looks like a banner. But that’s CSS’s job. ARIA roles describe structure, not appearance.

The fix. Remove the role entirely. The masthead is just a styled decorative element — no ARIA role needed. The page’s real site banner is the <nav> at the top, which Bootstrap handles automatically.

The Takeaway. Use CSS to control how things look. Use HTML structure and ARIA roles to describe what things are. Those are two completely separate jobs. Mixing them up breaks accessibility without breaking anything visible — which is exactly the kind of silent bug that’s hardest to catch.

DWR
06/03/2026

Hero Background Bleeds Outside the Image on Small Screens — background-size: cover to the Rescue

Read more…

First: how did we even find this? We tested the page at different screen sizes — shrinking the browser window down to phone width to see how it looked. That one habit caught this bug immediately. Always test at multiple screen sizes. A page that looks great on your laptop can be broken on the phone in your pocket, and you’ll never know unless you look.

The Problem

Imagine you hang a wide poster on a narrow wall. The poster is wide enough to cover the wall perfectly — but now imagine making the wall skinnier and skinnier. The poster shrinks with it, and eventually it’s so short that it doesn’t reach the bottom of the wall anymore. Bare wall shows below it.

That’s exactly what was happening to our hero section on phones. The CSS instruction background-size: 100% auto tells the browser: “make the image exactly as wide as the container, and figure out the height automatically (keep the proportions).” On a wide monitor that’s perfect. On a 390px-wide phone, the image width shrinks to 390px, and its proportional height drops too — often below the hero’s minimum height. So the bottom of the hero box had no photo behind it, just the browser’s default background color showing through, and the text was floating over nothing.

The Fix

The fix is a different CSS value: background-size: cover. Think of it like a different instruction to the browser: “scale the image until it completely fills the box — no bare spots allowed — even if that means cropping a little off the sides.” The whole hero box is always covered, no matter how narrow the screen gets.

We only needed this fix on small screens, so we used a media query — a CSS rule that only activates when the screen is below a certain width:

@media (max-width: 520px) {
    #hero {
        background-size: cover;
    }
}

Translation: “If the screen is 520 pixels wide or less, switch to cover mode.” Wider screens keep the original 100% auto look. Narrow screens switch to cover automatically. One problem, one fix, zero tradeoffs.

The Takeaway

background-size: 100% auto = “match my width exactly” (can leave gaps vertically on small screens).
background-size: cover = “fill the whole box, crop if needed” (no gaps, ever).
Media queries let you use different rules for different screen sizes — one of the most powerful tools in responsive design.

DWR
06/03/2026

rel="noopener noreferrer" — Why It Matters on Every External Link

Read more…

When you open a link in a new tab with target="_blank", the new page secretly gets a handle back to your page via window.opener. A malicious site could exploit that to silently redirect your original tab — a classic attack called reverse tabnapping:

// evil code on the destination site could do:
window.opener.location = "https://fake-login-page.com";

rel="noopener" cuts that connection: the new tab opens with window.opener === null, so the linked site can’t touch your page at all.

rel="noreferrer" goes one step further — it also suppresses the Referer HTTP header, so the destination site doesn’t even know which page sent the visitor. Best practice: use both together.

<a href="https://example.com" target="_blank"
   rel="noopener noreferrer">Link text</a>

It’s a free, zero-cost security habit. Add it to every target="_blank" link — always.

Eureka
06/03/2026

Fresh Start — 2026 TNT Upgrade

Read more…

As part of the 2026 TNT redesign, the old DWR & Eureka log was retired and this fresh version was born. The previous log (2022–2023) covered Bootstrap 5.0 quirks, case-sensitive filenames on servers, and data-type disasters in JavaScript — all still great lessons, preserved in origDwrEureka.html for posterity.

New entries will document discoveries and disasters from the 2026 upgrade onward: Bootstrap 5.3, CSS custom properties (design tokens), Font Awesome 6.5, separation-of-concerns CSS architecture, and whatever we stumble into next.

Eureka